2

私がこれを理解しているように、一部の数値は 2 進数で正確に表現できないため、浮動小数点演算で予期しない結果が生じることがあります。4.35 * 100 = 434.99999999999994 のように。10 進数の 1/3 で起こることと似たようなことです。

それは理にかなっていますが、これは別の疑問を引き起こします。バイナリでは、4.35 と 435 の両方を正確に表現できるようです。それが私にとって意味をなさないときです。4.35 * 100 が 434.99999999999994 と評価されるのはなぜですか? 435 と 4.35 は double 型のダイナミクスで正確に表現されます。

double number1 = 4.35;
double number2 = 435;
double number3 = 100;
System.out.println(number1); // 4.35
System.out.println(number2); // 435.0
System.out.println(number3); // 100.0
// So far so good. Everything ok. 

System.out.println(number1 * number3); // 434.99999999999994 !!!
// But 4.35 * 100 evaluates to 434.99999999999994

なんで?

編集:この質問は重複としてマークされましたが、そうではありません。受け入れられた回答でわかるように、私の混乱は、実際の値と印刷された値の不一致に関するものでした。

4

4 に答える 4

8

浮動小数点演算が予期しない結果をもたらすことがあるという点で、あなたは正しいです。

4.35浮動小数点で正確に表現できる アサーションは正しくありません。これは、終端の 2 進 10 進数として表現できないためです。100は明らかに正確に表すことができるので、結果が であるためには、 を正確に434.99999999999994表す`4.35必要はありません。

浮動小数点で正確に表現するには、数値を分母が 2 のべき乗のみの分数に変換できなければなりません (また、浮動小数点型の最大精度を超えるほど正確であってはなりません)。使用しています)。この場合、4.354 7/20であり、分母の因数は5であるため、数値を 2 進数で正確に表すことはできません。

于 2013-08-22T19:43:39.553 に答える
1

私はハンガリー語で計算機の数値表現を学んでいるので、英語で説明するのは少し難しいです。つまり、4.35、435、100 は正確にはこれらの数値ではありませんが、仮数 * 2^k (-k から +k までの k-特性、および t - は M = (t,-k, +k) ) ただし、print 呼び出しは丸めを行います。したがって、数直線は連続ではありませんが、いくつかの有名なポイントの近くでは、より密になります)。

浮動小数点数直線

したがって、これらの数値はあなたが期待するものとまったく同じではないと思うので、操作後 (これは 1 つまたは 2 つの単純なバイナリ操作だと思います)、2 つの浮動小数点数表現の誤差距離の倍数が得られます。

于 2013-08-22T20:44:31.597 に答える
1

ハードウェアの観点からは、各浮動小数点数は M * 2^E (ここでM、 とEは特定の範囲の整数) の形式の正確な値を表しますが、ソフトウェアの観点からは、各浮動小数点数を次のように考えるとより役に立ちます。 「M * 2^E が最良の表現と見なされ、できればそれに近いもの」を表します。浮動小数点値 (M * 2^E) が与えられた場合、それが表現しようとしている実際の数値は、(N - 1/2) * 2^E から (N + 1/2) までの範囲のどこかに非常に簡単に収まる可能性があることを理解する必要があります。 * 2^E であり、実際にはもう少し拡張される場合があります。

簡単な例として、 typeを使用floatすると、 の値はM0 ~ 16777215 の範囲に制限されます。したがって、2000000.1f の最適な表現は 16000001 * 2^-3 [つまり、16000001/8] です。16000001/8 の正確な 10 進値は 2000000.125 ですが、16000001/8 が 2000000.120 と 2000000.129 (または、さらに言えば、2000000.0625 と2000000.1875、非包括的)。M * 2^E 形式の数値の正確な 10 進値を表示するために必要な桁数は、意味のある桁数をはるかに超えることが多いため、表示される桁数を、一意に表示するために必要な桁数に制限するのが一般的です。値を定義します。

浮動小数点数を範囲を表すものと見なす場合、doubletoからのキャストfloatは明示的に指定する必要がありますが、実際には安全であることに注意しdoublefloatください。floatその値またはそれに非常に近いもの。逆に、 からfloatdoubleの変換は、暗黙的に許可されていても危険です。そのような変換では、 が表すはずdoubleの数値を最もよく表す が選択される可能性が非常に低いためfloatです。

于 2013-08-22T20:43:35.890 に答える