我正在尝试使用java进行一些数学运算,如果它是(un)偶数,它会测试一个数字,只要它变为1就可以改变它。
我尝试运行我的循环999999次,它似乎卡在大约120000次。好吧,它不是停留在一个异常,它只是觉得编译器卡住了。
我对Java不太好,有人可以解释一下这里发生了什么吗?
public static void main(String[] args) {
int n = 0;
int highestNumber = 0;
int highestCounter = 0;
int counter = 0;
for (int i = 2;i<1000000;i++) {
if (i%10000==0) {
System.out.println(i);
}
n = i;
while (n!=1) {
if (n%2==0) {
n = n/2;
} else {
n=3*n+1;
}
counter++;
}
if (counter>highestCounter) {
highestCounter = counter;
highestNumber = i;
System.out.println("HIGHEST "+highestNumber+" | counter = "+counter);
}
counter = 0;
n = 0;
}
System.out.println("final "+highestNumber);
}
答案 0 :(得分:10)
因为3 * n + 1
变得大于Integer.MAX_VALUE
而导致溢出。所以n
变为负数,而while循环永远不会停止。
long
使用int
代替n
!
如果您想检查溢出:
while (n != 1) {
if (n % 2 == 0) {
n = n / 2;
} else {
if (n > (Integer.MAX_VALUE - 1) / 3) {
throw new RuntimeException("overflow!");
}
n = 3 * n + 1;
}
counter++;
}
Java 8的增加
从Java 8开始,Math
类为'精确'算术(加法,减法,乘法,除法)提供了额外的静态方法,在溢出的情况下抛出ArithmeticException
。使用这些方法,代码可以简化:
while (n != 1) {
if (n % 2 == 0) {
n = n / 2;
} else {
n = Math.addExact(Math.multiplyExact(3, n), 1);
}
counter++;
}
答案 1 :(得分:4)
你有一个溢出问题。像这样更改代码,你就会看到它:
while (n!=1) {
if(n < 0) throw new IllegalStateException("n should not become < 0" + n + "-" + counter);
if(n > ((Integer.MAX_VALUE -1) / 3)) System.out.println("n too large. " + n);
if (n%2==0) {
n = n/2;
} else {
n=3*n+1;
}
counter++;
}
如果您将n
设为long
,则可以正常使用。
答案 2 :(得分:1)
是n是整数吗?如果它很短,你可能会溢出它。
除此之外,整数的最大值超过20亿,所以你不应该打它。为了以防万一,尝试将n设置为long以查看是否有帮助
编辑:例如,数字77671根据我读过的博客(读取:未经测试),i = 77671的最高n为1,047,216,490
所以我认为n应该很长,现在我想更多关于它
答案 3 :(得分:1)
此更正有效:
public static void main(String []args){
long highestCounter = -1;
long highestNumber = -1;
for (long i = 2;i<1000000;i++) {
if (i%1000==0) {
System.out.println(i);
}
long n = i;
long counter = 0;
while (n!=1) {
if (n%2==0) {
n = n/2;
} else {
n=3*n+1;
}
counter++;
}
if (counter>highestCounter) {
highestCounter = counter;
highestNumber = i;
System.out.println("HIGHEST "+highestNumber+" | counter = "+counter);
}
counter = 0;
n = 0;
}
System.out.println("final "+highestNumber);
}
答案 4 :(得分:0)
您只是在阻止内部运行无限循环,在System.out.println(counter);
之后添加counter++
以查看正在发生的事情。