java - StackOverflowError 异常破坏有趣和复杂的程序

标签 java stack-overflow

所以这个问题有点复杂,很难理解我要做什么。

基本上,我试图随机生成 3 个大小均为 11 的 vector 。

第一个 vector 必须在位置 0 处有一个 1,接下来的 5 个位置为 0(例如 100000),而接下来的五个数字可以是 0 1 或 2,但是最后 5 个数字中只能使用一个零,因此 10000012101 将有效,但 10000012001 则无效。

这同样适用于第二个和第三个 vector ,但是第一个 1 将为第二个和第三个移动一个位置(第二个为 010000xxxxx,第三个为 001000xxxxx)。

还有更多的条件需要满足。每个 vector 必须至少有 5 个位置彼此不同(10000011210 与 01000022100 有 5 个位置不同,这是可行的)。

但是,还有一个最后的约束条件,即如果您将 vector 以 3 为模相加,则将这两个 vector 相加的结果必须在 vector 中至少有 5 个非零值。

我已经通过使用数组列表来解决这个问题。据我所知,每个 vector 的每个数组列表的前 6 个元素是我手动放入的,对于接下来的 5 个元素,我随机分配这些元素,如果最后五位数字中有一个以上的 0,我将再次递归调用该方法。

这个程序的问题是,当我尝试运行我的代码时,它出现了一个
线程“main”中的异常 java.lang.StackOverflowError 在 java.util.ArrayList.get(未知来源)

我认为这是因为它不断尝试循环并因此崩溃,但我不确定。请参阅下面的代码。

import java.util.ArrayList;

/**
 * The purpose of this class is to be able to capture different ways 
 * of generating six vectors that will produce a collection of 729 
 * vectors that guarantee 9 out of 11 correct. 
 */

public class GenerateVectors {

    static ArrayList<Integer> firstVector = new ArrayList<Integer>();
    static ArrayList<Integer> secondVector = new ArrayList<Integer>();
    static ArrayList<Integer> thirdVector = new ArrayList<Integer>();
    static ArrayList<Integer> sumOfXandY = new ArrayList<Integer>();

    //Creates the first vectors to ensure it starts with "1,0,0,0,0,0" 
    //and has at most one more zero in the last 5 digits
    public void createFirstVector(){

        int[] fir stVector1 = {1,0,0,0,0,0};
        for (int i=0; i<firstVector1.length; i++) {
            firstVector.add(firstVector1[i]);
        }
        for(int i = 0; i < 5; i++){
            int x = (int) (Math.random()*3);
            firstVector.add(x);
    }
    int j = 0;
    for(int i = 6; i<firstVector.size(); i++){
        if(firstVector.get(i).equals(0)){
            j++;
        }
    }
    if(j>1){
        OneZeroInLastFive(firstVector);
    }


    int[] sum = {0,0,0,0,0,0,0,0,0,0,0};
        for (int i=0; i<sum.length; i++) {
            sumOfXandY.add(sum[i]);
        }
    }

    //Edits the vector if there is more than 0 in the last five digits
    public void OneZeroInLastFive(ArrayList<Integer> x){
        int j = 0;
        for(int i = 6; i<x.size(); i++){
            if(x.get(i).equals(0)){
                j++;
            }
        }
        if(j>1){
            x.set(6, (int) (Math.random()*3));
            x.set(7, (int) (Math.random()*3));
            x.set(8, (int) (Math.random()*3));
            x.set(9, (int) (Math.random()*3));
            x.set(10, (int) (Math.random()*3));
            j = 0;
            OneZeroInLastFive(x);
        }
    }


    //Creates the second vector with the last 5 digits random
    public void createSecondVector(){
        int[] secondVector1 = {0,1,0,0,0,0};
        for (int i=0; i<secondVector1.length; i++) {
            secondVector.add(secondVector1[i]);
        }
        for(int i = 0; i < 5; i++){
            int x = (int) (Math.random()*3);
            secondVector.add(x);
        }
    }

    //Creates the third vector with the last 5 digits random
    public void createThirdVector(){
        int[] thirdVector1 = {0,0,1,0,0,0};
        for (int i=0; i<thirdVector1.length; i++) {
            thirdVector.add(thirdVector1[i]);
        }
        for(int i = 0; i < 5; i++){
            int x = (int) (Math.random()*3);
            thirdVector.add(x);
        }
    }

    /**
     * Will edit the second vector to ensure the following conditions are satisfied 
     * - The sum of x and y modulo 3 has at least 5 NON zeros
     * - x and y must DIFFER in at least 5 places 
     * - There is only one zero within the last 5 digits 
     *
     */
    public void checkVectors(ArrayList<Integer> x, ArrayList<Integer> y){
        int k = 0;
        int m = 0;
        for(int j = 0; j < x.size(); j++){
            if(x.get(j).equals(y.get(j))){
                ;
            }
            else{
                k++;
            }   
        }
        for(int i = 6; i<y.size(); i++){
            if(y.get(i).equals(0)){
                m++;
            }
        }
        if((k>4 && m<1)&& checkNonZeros(x,y)){

            System.out.println("Conditions met");
        }
        else{
            y.set(6, (int) (Math.random()*3));
            y.set(7, (int) (Math.random()*3));
            y.set(8, (int) (Math.random()*3));
            y.set(9, (int) (Math.random()*3));
            y.set(10, (int) (Math.random()*3));
            k = 0;
            m = 0;
            checkVectors(x,y);
        }
    }


    public ArrayList<Integer> addTwoVectors(ArrayList<Integer> x, ArrayList<Integer> y, ArrayList<Integer> z){
        for(int i = 0; i<x.size(); i++){
            int j = x.get(i);
            int k = y.get(i);
            z.set(i, ((j+k)%3));
        }
        return z;
    }


    public boolean checkNonZeros(ArrayList<Integer> x, ArrayList<Integer> y){
        addTwoVectors(x,y, sumOfXandY);
        int j = 0;
        for(int i = 0; i<firstVector.size(); i++){
            if(sumOfXandY.get(i).equals(0)){
                ;
            }
            else{
                j++;
            }
        }
        if(j<5){
            return false;
        }
        else {
            return true;
        }
    }

    public static void main(String[] args){
        GenerateVectors g = new GenerateVectors();
        g.createFirstVector();
        g.createSecondVector();
        g.createThirdVector();

        g.checkVectors(firstVector,secondVector);
        g.checkVectors(secondVector,thirdVector);

        System.out.println(firstVector);
        System.out.println(secondVector);
        System.out.println(thirdVector + "\n");

        System.out.println(g.checkNonZeros(firstVector, secondVector));
        System.out.println(g.checkNonZeros(secondVector,thirdVector));
        System.out.println(sumOfXandY);
    }

}

任何帮助将不胜感激!!!

最佳答案

问题是您有递归调用自身以“重做”的方法,在您获得成功之前可能会发生很多次。这在 scheme 或 ml 等执行适当尾递归的语言中很好,但 java 没有,因此您会遇到堆栈溢出。

为了解决这个问题,您需要手动将递归代码转换为循环。看起来像的代码:

method(arg1, arg2) {
    Code_block_1;
    if (test) {
        Code_block_2;
    } else {
        Code_block_3;
        method(newarg1, newarg2);
    }
}

需要变成这样的:

method(arg1, arg2) {
    Code_block_1;
    while(!test) {
        Code_block_3;
        arg1 = newarg1;
        arg2 = newarg2;
        Code_block_1;
    }
    Code_block_2;
}

然后,如果您愿意,您可以重构内容以删除/合并重复的代码。

关于java - StackOverflowError 异常破坏有趣和复杂的程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8736077/

相关文章:

java - Logback - 如何通过配置文件设置滚动日志的新开始和新的一天

java - 提示用户输入3个数字,添加最大的2个数字(无法调用方法)

mvvm - 我怎样才能避免这个无限循环?

java - 记录生成的 CXF 客户端的原始 XML

java - 在Java中使用byte[]数组将.gz文件分割成指定的文件大小

java - Java EE 应用程序是否有 "Socket Connection Pool"之类的代码?

performance - Haskell:在大列表中找到最大值时堆栈溢出

c# - 属性引起的 Stackoverflow 异常

java - 为什么这段代码会抛出 StackOverflowError

c - 运行时错误(堆栈溢出)