1

以下を試してみましたが、「test」の値が間違っているようです。2500 * 2500 * 2500 == 15625000000、なぜ以下の操作で異なる結果になるのですか?

unsigned long long int test = 2500*2500*2500;
fprintf(stderr, "*************** test = %lld, %llu\n", test, test);
unsigned long long int test2 = 15625000000;
fprintf(stderr, "*************** test2 = %lld, %llu\n", test2, test2);

結果:

*************** test = -1554869184, 18446744072154682432
*************** test2 = 15625000000, 15625000000
4

2 に答える 2

3

2500 * 2500 * 2500は を超えてプロモートされることはないintため、符号付きオーバーフロー (ちなみに UB) が発生すると、正しい計算が実行されなくなります。

これを許可するには、リテラルが特定の型であることをコンパイラに伝える必要があります。これを行うには、次の 2 つの方法があります。

  1. キャストによる — リテラルのキャストは通常​​、コンパイル時に処理され、実行時のオーバーヘッドはありません。

    unsigned long long int test = (unsigned long long int)2500 * (unsigned long long int)2500 * (unsigned long long int)2500;
    

    キャストは被乗数に対して個別に実行されることに注意してください。操作の結果がキャストされた場合 (例: (unsigned long long int)(2500 * 2500 * 2500))、データを保存するにはキャストが遅すぎます。

  2. 接尾辞:

    unsigned long long int test = 2500ULL * 2500ULL * 2500ULL;
    

    これは実行時にリテラルのキャストとまったく同じくらい効率的ですが、使い方によっては読みやすくなったり難しくなったりします。接尾辞は、リテラルに直接適用する必要があります (演算の結果には適用できないため、 (2500 * 2500 * 2500)ULL違法です)。

于 2012-07-02T05:32:52.713 に答える
2

2500*2500*2500unsigned long longにコピーしているという理由だけで、unsignedlonglongではありません。乗算はintsで行われるため、乗算の結果は。になりintます。アップグレードが行われるまでにunsigned long longは、手遅れです。を使用し2500ULLます。

于 2012-07-02T05:32:10.773 に答える