为什么使用add2
方法的结果是错误的?Double.toString(d1)
为什么能保持double
的精度不丢失?
public static double add(double d1, double d2) {
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.add(bd2).doubleValue();
}
public static double add2(double d1, double d2) {
BigDecimal bd1 = new BigDecimal(d1);
BigDecimal bd2 = new BigDecimal(d2);
return bd1.add(bd2).doubleValue();
}
public static void main(String[] args) {
double d1 = 1.0000002;
double d2 = 0.0000002;
System.out.println(Double.toString(d1));
System.out.println("d1 + d2 = " + (d1 + d2)); // 1.0000003999999998
System.out.println("d1 + d2 = " + add(d1, d2)); // 1.0000004
System.out.println("d1 + d2 = " + add2(d1, d2)); // 1.0000003999999998
}
PS:引出一个概念问题:
double d = XXXX.XXXXXX;
System.out.println(d); //这里总是不会丢失精度的,为什么?
BigDecimal が入力パラメータとして double を使用する場合、バイナリは文字列 "0.0000002" と "1.0000002" を読み込んだ後、それを 8 バイトの double 値に変換する必要があります。これは次のようなものです。 。
System.out.println 部分では、入力パラメータが文字列の場合、それ以外の型の場合は Object.toString メソッドを呼び出して変換して出力します。 Double.toString は、出力する前に特定の精度を使用して double を丸めます。1.0000001999999998947288304407265968620777130126953125
したがって、実行時に実際に BigDecimal コンストラクターに渡される実際の値はです。
1.0000001999999998947288304407265968620777130126953125
BigDecimal は、String を入力パラメーターとして使用する場合、文字列を真に正確な浮動小数点数に正しく変換できます。リーリー
追加説明:
次に、このメソッドは
Double.toString
を出力し、四捨五入されます。String
入力パラメーターは処理後の
new BigDecimal(Double.toString(d1))
となり、String
コンストラクターが呼び出されます。BigDecimal(String val)
ソース コード内の BigDecimal(String val) メソッドは、val を char[] 配列に処理します。リーリー
コンストラクターを呼び出します。
そして新しい BigDecimal(d1) はBigDecimal(char[] in)
を呼び出します。このメソッドが入った後の最初の処理は
入力パラメータをバイナリに変換するため、精度が失われます。BigDecimal(double val)
です。 リーリー