Nik*_*Nik 6 java debugging for-loop
我正在编写这个问题来自Programming in Java book-site(对于实践,而不是HW .. Q15,见http://introcs.cs.princeton.edu/java/13flow/):
找到谐波系列的总和1/1 + 1/4 + 1/9 + 1/16 + ... + 1/N2.for循环有4种变体,其中一些应该给出正确的答案.我的预期答案在评论中,实际结果如下.
public class OneThreeExFifteen {
public static void main(String[] args) {
int N = 1000000;
double s1=0 , s2 = 0, s3 = 0, s4=0;
for (int i = 1; i <= N ; i++ )
s1 = s1 + 1 / ( i * i ); // Expected s1 = 1
for (int i = 1 ; i <= N ; i++ )
s2 = s2 + 1.0 / i * i; // Expected s2 = 1000000
for (int i = 1 ; i <= N ; i++)
s3 = s3 + 1.0 / (i * i) ; // Correctly computes the series sum
for (int i = 1; i <= N ; i++ )
s4 = s4 + 1 / (1.0 * i * i) ; // Correctly computes the serires sum
System.out.println("for loop 1" + s1);
System.out.println("for loop 2" +s2);
System.out.println("for loop 3" +s3);
System.out.println("for loop 4" +s4);
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
for loop 1 ( I get a Divide by 0 error - had to comment out this loop)
for loop 2 1000000.0
for loop 3 Infinity
for loop 4 1.64493306684877
Run Code Online (Sandbox Code Playgroud)
问题 - 为什么我会得到
a)除以零误差?
b)for loop 3的无限结果?
当然,正如另一个人已经说过的那样,你已经1 / ( i * i )在多个地方执行了整数除法.在Java中,int除以a int必须保持为a int,因此1除以更大的数量0.但是你不是因为这个原因而除以零.这只会让你加零,完美无异常.
您是循环的i,从0到1000000(100万).在你走得太远之前,i是65536(2至16强).当这个迭代发生时,i * i溢出("真实"结果是2^32),你得到0.该结果导致第一个循环中除以零.
示范计划:
public static void main (String args[]) throws IOException
{
int i = 1 << 16; // 2^16, or 65536
System.out.println(i);
int j = i * i;
System.out.println(j);
}
Run Code Online (Sandbox Code Playgroud)
输出:
65536
0
Run Code Online (Sandbox Code Playgroud)
第三个for循环非常相似,除了浮点除法产生Infinity(合法的浮点值)而不是除以零的错误.
第二个和第四个for循环double在操作之前正确地促进乘法运算,因此不会发生溢出.但是第二个for循环缺少其括号,因此1每次都添加.第四个for循环正确计算总和.