我有以下方法:
public static boolean[] mk2(int n) {
boolean[] isPrime = new boolean[n + 2];
isPrime[1] = false;
isPrime[2] = true;
for (int i = 3; i <= n; i++) {
if((i & 1) == 0) {
isPrime[i] = false;
} else {
isPrime[i] = true;
}
}
// cycle through to see if a number has factors other than 1 & itself
for(int y = 3; y <= n; y++) {
System.out.print("Test y " + y);
if(isPrime[y]) {
for(int i = 2; i <= y-1; i++) {
if(y%i==0){
// stop here if it isn't prime
isPrime[y] = false;
System.out.println(" disproved");
i = y + 1;
}
}
if(isPrime[y]){
System.out.println(" is prime and disproves:");
for (int j = y; y*j <= n; j++) {
if(y*j<=n) {
isPrime[y*j] = false;
System.out.print(" "+(y*j)+" ");
}
}
System.out.println(".");
}
} else {
System.out.println(" already disproved");
}
}
System.out.println("Primes");
int x = 0;
for(int i=1; i <= n; i++) {
if(isPrime[i]) {
System.out.print(i+", ");
x++;
}
if(x >= 61) {
System.out.println(";");
x = 0;
}
}
System.out.println(".");
return isPrime;
}
通常工作正常但是当我将n设置为100000时,我得到以下异常java.lang.ArrayIndexOutOfBoundsException: -2146737495
java.lang.ArrayIndexOutOfBoundsException
所以我对这里发生的事情感到有些困惑。 任何想法?
答案 0 :(得分:2)
错误很可能来自int
的算术溢出。
最可能的根本原因是您对元素isPrime[y*j]
的引用,其中y * j
溢出int
并返回Integer.MIN_VALUE + (the amount overflown - 1)
。
您应该设置断点并调试这些值。
答案 1 :(得分:1)
有问题的陈述是isPrime[y*j] = false;
,它会生成Integer
范围之外的数字。一旦达到最大数量并从否定数字开始,您就会得到异常,因为索引应为>= 0 and < len
更具体地说,您试图将y= 46349, j=46349
乘以2148229801
,其大于Integer.MAX_VALUE=2147483647
答案 2 :(得分:0)
当整数溢出时,它会回到最小值并且 从那里继续。如果它下溢,它会回到最大值 价值并从那里继续。
所以根据
java.lang.ArrayIndexOutOfBoundsException: -2146737495
因为索引必须是正数:
根据java语言规范:
在运行时检查所有数组访问;尝试使用索引 小于零或大于或等于的长度 数组导致抛出ArrayIndexOutOfBoundsException。
https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.13
答案 3 :(得分:0)
int是32位,long是64位。所以它提供了更大的范围。你应该做的是将变量j和y转换为longs:
for(long y = 3; y <= n; y++) {
for (long j = y; y*j <= n; j++) {
无论您将数组编入索引,都需要将其转换为
if(isPrime[(int)y]) {
发生的事情是你将两个超过int范围的整数相乘并因此变为负数且下面的条件满足为真:
if(y*j<=n) {
然后它试图在你的数组中分配一些负面索引:
isPrime[y*j] = false;