简体   繁体   中英

Why can't I set list.size as the length of my integer array?

I've been struggling for hours to eliminate a bug that I don't understand. In line 190 of the code below (int s = n[0]) I get an array out of bounds exception which as I've narrowed down has to do with array e. Array e is declared at the top of the code given below with the length/size of an object list a (a.size()) and if I replace size with an arbitrary integer (for example 10) the error disappears.

Why can't I set a.size as the length of my array? Is there a way to go around this?

Summary of the code: powerize(int n) is supposed to Write a number n as a power with maximal exponent. factorize decomposes a number into the product of primes and gcd returns the greatest common divisor of an array of integers.

public static Power powerize(int n) throws IllegalArgumentException {

    List<Power> a = MathStuff.factorize(n); //make a list of Power objects from factorize n
    int size = a.size();
    int[] e = new int[size];
    int[] b = new int[size];

    for (int i = 0; i < size; i++) { //collect all the base and exponent of each object in a. This LOOP 1
        if(i >= a.size() || i >= e.length || i > b.length){System.out.print("Out of bounds in LOOP 1");} //test for out of bounds
        e[i] = a.get(i).exponent;
        b[i] = a.get(i).base;
    }

    int g = gcd(e);


    int h = 1; //endproduct base
    for (int i = 1; i < b.length; i++) { //Construct the base by taking the product of each base with its exponent divided by g.
        if(i >= e.length || i >= b.length){System.out.print("Out of bounds in LOOP 3");} //test for out of bounds
        h *= MathStuff.power(b[i], e[i] / g);
    }

    return new Power(h, g); //replace 2

}


/**
 * factorize n
 *
 * @param n the number to 'powerize'
 * @modifies none
 * @pre {@code 2 <= n}
 * @return factorization of n
 */
public static List<Power> factorize(int n) {
    List<Integer> f = new ArrayList<Integer>(); // f are factors
    for (int i = 2; i <= n; i++) {
        while (n % i == 0) {
            f.add(i);
            n /= i;
        }
    }
    //return f; //returns factors

    List<Power> p = new ArrayList<Power>(); // p are the factors with powers
    for (int j = 2; j <= n; j++) { //j will be the base
        int e = 0; //exponent
        for (int k = 0; k <= f.size(); k++) {
            if (f.get(k) == j) {
                e++;
            }
        }
        p.add(new Power(j, e));
    }

    return p; //returns factors in powered form
}

/**
 * gcd returns the greatest common divisor of an integer array
 * @param n
 * @return greatest common divisor
 */
public static int gcd(int... n) {

    //------------------------------------------------THE ERROR OCCURS HERE
    int s = n[0];

    for (int i = 1; i < n.length; i++) {
        if (n[i] < s) {
            s = n[i];
        }
    }

    while (s > 1) {

        int counter = 0;
        int modTot = 0;

        while (counter < n.length) {

            modTot += n[counter] % s;
            counter++;

        }

        if (modTot == 0) {
            return s;
        }

        s--;

    }
    //return 0 if there is no gcd
    return 0;
}   

Here:

public static int gcd(int... n) {
 int s = n[0];

This code assumes (without any further checking) that gcd() was invoked with at least one array element. But obviously that is not true.

Keep in mind that you can invoke that method like:

gcd(); // NO array at all or
gcd(someArray); // but someArray happens to be null !

So you have to step back and check your source code for all situations where gcd() is called. There must be one where you pass 0 parameters; or you pass an array of int that is actually null.

I'll assume that your question is why you can't set the size of an array using the size property.

When an array is initialized (via new int[x] ), the OS will look for a continuous block of memory that will be big enough to hold x int s. Once that memory is found, the size of the array will be fixed as x .

Think of what would happen if you could change the array size using size . This would mean that, if you wanted to expand this array, you would have to take over the memory that comes immediately after it. What if that memory is being used by something else? That would present a problem.

However, java.util.ArrayList solves this problem for you as and when necessary. So that's the work-around if you need it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM