用于java中的循环调试 - 值溢出

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的无限结果?

rge*_*man 5

当然,正如另一个人已经说过的那样,你已经1 / ( i * i )在多个地方执行了整数除法.在Java中,int除以a int必须保持为a int,因此1除以更大的数量0.但是你不是因为这个原因而除以零.这只会让你零,完美无异常.

您是循环的i,从01000000(100万).在你走得太远之前,i65536(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循环正确计算总和.