6

この問題は、Programming in Java book-site から解決しています (HW ではなく、練習用です。http://introcs.cs.princeton.edu/java/13flow/の Q15 ):

調和級数 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);


    }
}

結果:

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

質問 - なぜ私は得るのですか

a) ゼロ除算エラー?

b) for ループ 3 の場合の無限大の結果 ?

4

4 に答える 4

3

ここで整数除算に苦しんでいます:

s1 = s1 + 1 / ( i * i );

iは でありint、接尾辞のないすべての数値は暗黙的intに であるため、幸運にも 1/1 を割ります。結果は 1 になります。

ただし、増加すると事態が発生しiます-1より大きい場合、ループの最後まですべての結果に対して0を取得します。

これを理解すると、デバッガーで異常なことが起こります。数字が 65536 2 のときにゼロ除算が発生します。つまり、2 3265536である65536 でオーバーフローが発生し、int 値が 0 になります。

2 番目のループ:

s2 = s2 + 1.0 / i * i;

演算子の優先順位にやけどを負っています。除算と乗算は加算よりも優先順位が高いため、これが実際に行っていることは次のとおりです。

s2 = s2 + ((1.0 / i) * i);

あなたは正しく除算しますが、演算子の優先順位はすべて間違っています。

3 番目のループ:

s3 = s3 + 1.0 / (i * i) ;

これは上記と同じ問題ですが、浮動小数点のコンテキストにいるため、0 で割ったものはすべて signed になりInfinityます。

于 2013-11-08T19:31:25.117 に答える
3

System.out.println(65536*65536);

これは 0 を出力します。

これは、0 による除算の問題を説明していると思います。整数オーバーフローが発生しています。整数は、特定のポイントまでの数値のみを保持できます。

ただし、他の場所で述べたように、整数除算はあなたを大いに傷つけています。0 で除算できなかったとしても、整数除算のために答えが間違っています。

于 2013-11-08T19:42:03.443 に答える
0

最初のものは単なるオーバーフロー バグです。これを証明する簡単な方法の 1 つは、除算前の i の値を表示することです (65536 または 2^16 になります)。int の制限は 2^32 であり、整数は最大値を超えるとループするため、2^32 = 0 になります。

(私 * 私) = (2^16 * 2^16) = 2^32 = 0

于 2013-11-08T19:43:44.763 に答える