1

重複の可能性:
double で小数点以下の桁数を移動する

Javaでこの奇妙な問題が発生しています。次のコードがあります。

double velocity = -0.07;
System.out.println("raw value  " + velocity*200 );
System.out.println("floored value  " + Math.floor(velocity*200) );

次の出力があります。

raw value  -14.000000000000002
floored value  -15.0

これらのtraling 0002はすべてを台無しにします.ところで、そのtraling 2があるべきではありません.小数点以下はすべてゼロであるべきだと思います.その2を取り除くことはできますか?

更新: 助けてくれてありがとう、みんな、doubleValue メソッドを呼び出さずに BigDecimal オブジェクトで床を丸める方法を知っていますか?

4

4 に答える 4

4

だってfloor(-14.000000000000002)本当に-15

ご覧floorのとおり、 は引数以下の最大の整数として定義されています。は整数ではないので-14.000000000000002、下に最も近い整数 -15です。

-0.07 * 200さて、ここで が厳密に ではない理由を明確にしましょう-14。これは、浮動小数点数の内部表現が base2にあるためです。そのため、分母がべき乗でない分数は2100% の精度で表すことができません。(小数点以下の桁数が有限の小数として 1/3 を表すことができないのと同じ方法です。) したがって、 の値は正確には でvelocityはありません-0.07。(コンパイラは、定数-0.07を検出すると、それを に非常に近いが-0.07、実際には等しくない 2 進数の分数に静かに置き換えます。) これが、velocity * 200が正確に ではない理由です-14

于 2012-05-15T13:57:34.157 に答える
3

浮動小数点ガイドから:

0.1 + 0.2 などの数値を足して 0.3 にならず、代わりに 0.30000000000000004 のような奇妙な結果が得られるのはなぜですか?

内部的に、コンピューターは 0.1、0.2、0.3 などの数値を正確に表すことができない形式 (2 進浮動小数点) を使用しているためです。

コードがコンパイルまたは解釈されると、「0.1」はすでにその形式の最も近い数値に丸められているため、計算が行われる前でも小さな丸め誤差が発生します。

特定の期待値に正確に加算される数値が必要な場合は、 を使用できませんdouble。詳しくはリンク先のサイトを読んでください。

于 2012-05-15T13:51:34.513 に答える
2

BigDecimal を使用してください... 上記の問題は、有限メモリのコンピューターで使用される表現スキームでよく知られている丸めの問題です。問題は、答えが 2 進数 (つまり、基数 2) システム (つまり、10 進数で 1/3 = 0.33333333... のように) で反復的であり、正しく表示できないことです。これの良い例は 1/10 = 0.1 で、バイナリでは 0.000110011001100110011001100110011... です。ある時点の後、1 と 0 が終了する必要があり、認識されたエラーが発生します。

あなたが命にかかわるものに取り組んでいないことを願っています...たとえばhttp://www.ima.umn.edu/~arnold/disasters/patriot.html。丸め誤差により 28 人が死亡した。

于 2012-05-15T13:47:44.233 に答える
1

Java double は、IEEE 754 浮動小数点演算に従います。これは、すべての実数を無限の精度で表すことはできません。この切り上げは正常です。内部表現ではそれを取り除くことはできません。もちろん、 String.format を使用して結果を出力できます。

于 2012-05-15T13:49:26.870 に答える