2

3 つの数を乗算しようとしましたが、奇妙な結果が得られます。なぜこんなに違う結果が得られるのですか?

unsigned int a = 7;
unsigned int b = 8;
double d1 = -2 * a * b;
double d2 = -2 * (double) a * (double) b;
double d3 = -2 * ( a * b );

// outputs:
// d1 = 4294967184.000000
// d2 = -112.000000
// d3 = 4294967184.000000
4

4 に答える 4

10

最初の例では、数値-2は unsigned int に変換されます。乗算の結果は -112 になり、符号なしで表すと 2^32 - 112 = 4294967184 になります。その後、この結果は最終的にdouble代入のために に変換されます。

2 番目の例では、すべての計算が double で行われ、正しい結果が得られます。次の場合、同じ結果が得られます。

double d3 = -2.0 * a * b

文字通り-2.0ですdouble

于 2012-10-06T17:09:16.023 に答える
3

double が署名されています。これは、最初のビット (最上位ビット、別名符号ビット) が、この数値が正か負かを決定することを意味します。

unsigned int は、最初のビット (最上位ビット) を使用して表現できる「正の」数値の範囲を拡張するため、負の値を処理できません。そうで

double d1 = -2 * a * b;

実行すると、マシンは (-2 * a * b) 全体を unsigned int 構造体 (a や b など) に配置し、次のバイナリ 1111 1111 1111 1111 1111 1111 1001 0000 を生成します (これは 112 の 2 の補数であるため) 0000 0000 0000 0000 0000 0000 0111 0000 です)。しかし、ここでの問題は、それが unsigned int であるため、最初の 1 を符号ビットとして扱わないため、非常に大きな正の整数 (4294967184) として扱われることです。

次に、それを double に入れるので、.00000 が印刷されます。

もう 1 つの例は、a を double に、b を double に型キャストするため機能します。そのため、-2 を double で乗算すると、コンピューターはそれを double 構造に配置するため、符号ビットが考慮されます。

double d3 = -2 * (double) (a * b)

同様に動作します。

署名付きと署名なしの感覚を得るには、これを確認してください

于 2012-10-06T17:28:53.930 に答える
1

C および C++ では、組み込み演算子は常に同じ型の 2 つの変数に適用されます。非常に正確な一連のルールにより、2 つの変数のうちの 1 つ (または 2 つ) が最初に異なる場合 (または小さすぎる場合) の昇格がガイドされます。

この正確なケースで-2は、 はデフォルトで型signed int( と同義int) でありa、 とbは型unsigned intです。この場合、ルール-2は に昇格する必要があると述べunsigned intています。システムではおそらく 32 ビットintと 2 の補数表現があるため、これは最終的に2**32 - 2(4 294 967 294) になります。次に、この数値に を掛けてa、その結果をモジュロ2**32(4 294 967 282) にします。次に、再びbモジュロ(4 294 967 184) にします。2**32

これは実に奇妙なシステムであり、数え切れないほどのバグが発生しています。たとえば、オーバーフロー自体が今年の 6 月 30 日に発生した Linux のバグにつながり、世界中の非常に多くのコンピューターが停止しました。いくつかの Java システムもクラッシュしたと聞いています。

于 2012-10-06T17:50:16.997 に答える
1

double d1 = -2 * a * b;

右辺はすべて整数型なので、右辺は整数型として計算されます。a署名されbていないため、結果の特定のタイプが決まります。それはどう-2ですか?に変換されますunsigned int。負の整数は、2 の補数演算を使用して符号なし整数に変換されます。これ-2は非常に大きな正の符号なし整数になります。

double d2 = -2 * (double) a * (double) b;

右側は整数と浮動小数点数が混在しているため、右側は浮動小数点型として計算されます。それはどう-2ですか?double に変換されます。これで、変換は簡単です: -2a に変換すると、 にdoubleなり-2.0ます。

于 2012-10-06T17:12:30.733 に答える