0

私は自分のアプリケーションで多くの浮動小数点演算を行っています。浮動小数点演算が 100% 正確ではないことは承知していますが、結果を印刷する場合は、適切にフォーマットする方法をまだ見つけていません。 .

例えば

0.1 + 0.1 = 0.1999999999999999999999

Math.sin(Math.PI) = 0 ではなく 1.2246E16

1.000000000000000001のようなもの

これらの結果を取得し、適切な丸められた値を取得する一般的な方法を探しています (文字列形式で)

0.1 + 0.1 = 0.19999999999999999999999 -> 0.2 これは切り上げが必要です

Math.sin(Math.PI) = 1.2246E16 -> 0

そして 1.000000000000000001 -> 1 のようなもの。これは切り捨てが必要ですが

また、結果が 1.1234567891234567 または 1.33333333333333 のような場合にデータが失われるのを避けたいと思います。これらの場合、結果は同じままでなければなりません。

4

3 に答える 3

1

書式設定の使用を避けたい場合は、結果を印刷する前に固定精度に丸め、Java が表現エラーを隠すために少量の丸めを行うという事実を利用することができます。

例 小数点以下 6 桁まで

public static double round6(double d) {
    return Math.round(d * 1e6) / 1e6;
}

round()との結果は1e6正確に表すことができます。さらに、「IEEE 754では正しい丸めが必要です。つまり、丸められた結果は、値を計算するために無限に正確な算術演算が使用されてから丸められたかのようになります」残っている唯一のエラーは、最も近い表現可能な値を取るための表現エラーです。Java の toString() は、より短い 10 進数の最も近い表現可能な値を持つ double がある場合、それが見たいものであると想定しています。

例 0.1 の実際の値は

System.out.println(new BigDecimal(0.1));

版画

0.1000000000000000055511151231257827021181583404541015625

ただし、Double.toString() にこの値が渡されると、0.1 がこの double に変換されると判断されるため、これが表示されます。

ところでJava 6には、最小桁数を使用しないというバグがあります。

for (int i = 1; i <= 9; i++)
    System.out.print(i / 1000.0 + " ");

Java 6プリントで

0.0010 0.0020 0.0030 0.0040 0.0050 0.0060 0.0070 0.0080 0.0090

そしてJava 7プリントで

0.001 0.002 0.003 0.004 0.005 0.006 0.007 0.008 0.009

パフォーマンスが重要でない場合はよく printf を使用します。重要な場合は、カスタム ルーチンを使用して double を直接 ByteBuffer に固定精度で書き込みます (効果的に丸めます)。これは、オブジェクトを作成しないため高速です。

また、結果が 1.1234567891234567 または 1.33333333333333 のような場合にデータが失われるのを避けたいと思います。これらの場合、結果は同じままでなければなりません。

その場合、結果を表示する必要があるまで結果を丸めないでください。

于 2012-10-31T13:13:36.097 に答える
1

例を使用してフォーマットしますSystem.out.printf("%.6f", myFloat)

于 2012-10-31T13:03:25.573 に答える
0

小数を失うのを避けたい場合は、float の代わりに BigDecimal を使用してください。遅くなりますが、より正確になります。

于 2012-10-31T13:04:02.823 に答える