質問

long long int A = 3289168178315264;
long long int B = 1470960727228416;
double D = sqrt(5);

long long int out = A + B*D;

printf("%lld",out);

これにより結果が得られます:-2147483648

理由はわかりません(肯定的な結果になるはずです)。 誰か助けてもらえますか?

役に立ちましたか?

解決

私の推測では、コンパイラは" A + B * D"の結果を丸める必要があります。 intフィールド内に結果を保存しているため、最初に整数に変換します。基本的に、データ型の競合が発生しています。

AとBはどちらも、long long intの有効な数値であり、8バイト長です。それらに1.000を掛けても、有効なlong long int値を保持できます。他のいくつかの言語では、int64としても知られています。

ただし、doubleも64ビットですが、その一部は指数として使用されます。 doubleをint64で乗算すると、結果は別のdoubleになります。別のint64を追加しても、二重になります。次に、特定の丸め方法を使用せずに、結果を再びint64に割り当てます。コンパイラがこのために4ビットの丸め関数を使用しても驚かないでしょう。コンパイラーがそのステートメントを軽視したり壊したりしないことにも驚いています!

とにかく、このような大きな数値を使用する場合、異なるタイプを混在させるときは特に注意する必要があります。

他のヒント

これらの定数を「long long」として指定する必要があるかもしれません。リテラル?例えば 3289168178315264LL

使用しているコンパイラ/オペレーティングシステムWindows XPおよびIT WORKSでVisual C ++ 2008 Express Editionを使用してコードを実行しました-回答:6578336356630528(これは53ビットの数値であるため、二重に収まります)。

また、操作の順序が重要かどうかを確認するために2つのバリエーションを試しました:

long long int out = A; out + = B * D;

long long int out = B * D; out + = A;

これらは両方とも機能します!

好奇心。

あなたの答え(検証する必要があります)は正常に計算されますが、符号ビットにオーバーフローが発生し、答えが否定になります。解決策:すべての変数を符号なしにします。

理由:

数字は一連のビットとしてコンピューターのメモリに保存されます。このようなシリーズの最初のビットは、設定されている場合、あなたが負の数であることを意味します。したがって、計算は機能しますが、符号ビットにオーバーフローします。

推奨事項:

これほど大きな数値を扱う場合は、多精度の算術ライブラリを入手することをお勧めします。 'Tは時間と手間を大幅に節約します。

sqrtのパラメーターは double である必要があります。

#include <math.h>
double sqrt( double num );

また、結果をB * Dからlong longに明示的にキャストする必要があります。

    long long int A = 3289168178315264;
    long long int B = 1470960727228416;
    double D = sqrt(5.0);
    printf("%f\n",D);
    long long int out = A + (long long) (B * D);
    printf("%lld",out);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top