web-dev-qa-db-ja.com

doubleをBigDecimalに変換し、BigDecimal Precisionを設定します

Javaでは、double値を取得してBigDecimalに変換し、その文字列値を特定の精度で出力します。

import Java.math.BigDecimal;
public class Main {
    public static void main(String[] args) {
        double d=-.00012;
        System.out.println(d+""); //This prints -1.2E-4

        double c=47.48000;
        BigDecimal b = new BigDecimal(c);
        System.out.println(b.toString()); 
        //This prints 47.47999999999999687361196265555918216705322265625 
    }
}

この巨大なものを印刷します:

47.47999999999999687361196265555918216705322265625

ではなく

47.48

私がBigDecimal変換を行う理由は、倍精度の値に小数点以下の桁が多く含まれる場合があり(つまり、-.000012)、倍精度を文字列に変換すると科学表記法-1.2E-4が生成されるためです。非科学表記法で文字列値を保存したい。

BigDecimalには、常に「47.48」のような2つの精度単位が必要です。 BigDecimalは、文字列への変換の精度を制限できますか?

55
c12

別の MathContext を使用すると、47.48000が出力されます。

BigDecimal b = new BigDecimal(d, MathContext.DECIMAL64);

必要なコンテキストを選択してください。

46

このような動作の理由は、印刷される文字列が正確な値-おそらく期待したものではないが、メモリに保存される実際の値-浮動小数点表現の制限にすぎないためです。

Javadocによると、BigDecimal(double val)コンストラクターの動作は、この制限を考慮しないと予期しないものになる可能性があります。

このコンストラクタの結果は、いくぶん予測不能です。 Javaに新しいBigDecimal(0.1)を書き込むと、0.1(スケールなしの値1、スケール1)に完全に等しいBigDecimalが作成されますが、実際には0.1000000000000000055511151231257827021181583404541015625に等しくなります。これは、0.1をdoubleとして正確に表現できないためです(つまり、有限長の2進小数として表現することはできません)。したがって、コンストラクターに渡される値は、外観にかかわらず、0.1に正確には等しくありません。

だからあなたの場合、代わりに

double val = 77.48;
new BigDecimal(val);

つかいます

BigDecimal.valueOf(val);

BigDecimal.valueOfによって返される値は、Double.toString(double)の呼び出しの結果と同じです。

91
omnomnom

String.format("%f", d)を試してみてください。これは、10進表記でdoubleを出力します。 BigDecimalを使用しないでください。

精度の問題に関して:最初に47.48double cを保存し、次にそのBigDecimalから新しいdoubleを作成します。精度の低下は、cへの割り当てにあります。できる

BigDecimal b = new BigDecimal("47.48")

精度が失われないようにします。

15

何故なの :

b = b.setScale(2, RoundingMode.HALF_UP);
5
urOutsourced

doubleの実際の正確な値を出力しています。

doublesをStringsに変換するDouble.toString()は、not入力の正確な10進値を出力します-xがあなたのdouble値の場合、 xが印刷した値に最も近いdoubleになるように正確に十分な桁を出力します。

ポイントは、そのようなdoubleはないが正確に47.48であるということです。 Doublesは、値をbinary decimalとしてではなく、分数として格納するため、正確なdecimal値を格納できません。 (それがBigDecimalの目的です!)

5
Louis Wasserman

String.format構文は、doubleおよびBigDecimalsを任意の精度の文字列に変換するのに役立ちます。

このJavaコード:

double dennis = 0.00000008880000d;
System.out.println(dennis);
System.out.println(String.format("%.7f", dennis));
System.out.println(String.format("%.9f", new BigDecimal(dennis)));
System.out.println(String.format("%.19f", new BigDecimal(dennis)));

プリント:

8.88E-8
0.0000001
0.000000089
0.0000000888000000000
3
kk yadav
BigDecimal b = new BigDecimal(c).setScale(2,BigDecimal.ROUND_HALF_UP);
2
Leaxus

Java 9では、以下は非推奨です。

BigDecimal.valueOf(d).setScale(2, BigDecimal.ROUND_HALF_UP);

代わりに使用します:

BigDecimal.valueOf(d).setScale(2, RoundingMode.HALF_UP);

例:

    double d = 47.48111;

    System.out.println(BigDecimal.valueOf(d)); //Prints: 47.48111

    BigDecimal bigDecimal = BigDecimal.valueOf(d).setScale(2, RoundingMode.HALF_UP);
    System.out.println(bigDecimal); //Prints: 47.48
0
jbilander