88

BigDecimalJava では、double 値を取得して a に変換し、その String 値を特定の精度で出力し たいと考えています。

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変換を行っている理由は、double 値に多くの小数点以下の桁数 (つまり-.000012) が含まれる場合があり、double を String に変換すると科学的表記法が生成されるため-1.2E-4です。文字列値を非科学的な表記で保存したい。

BigDecimal には、「47.48」のように常に 2 つの精度単位を持たせたいと考えています。BigDecimal は文字列への変換時に精度を制限できますか?

4

8 に答える 8

139

このような動作の理由は、出力される文字列が正確な値であるためです。おそらく期待したものではありませんが、これはメモリに格納されている実際の値です。これは、浮動小数点表現の制限にすぎません。

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

このコンストラクターの結果は、予測できない場合があります。Java で new BigDecimal(0.1) を書き込むと、正確に 0.1 に等しい BigDecimal (スケール 1 のスケールなしの値 1) が作成されると思われるかもしれませんが、実際には 0.1000000000000000055511151231257827021181583404541015625 に等しくなります。これは、0.1 を double として正確に表現できないためです (さらに言えば、有限長の 2 進小数としても表現できません)。したがって、コンストラクターに渡される値は、見た目はともかく、0.1 と正確には等しくありません。

したがって、あなたの場合、使用する代わりに

double val = 77.48;
new BigDecimal(val);

使用する

BigDecimal.valueOf(val);

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

于 2013-05-27T13:24:34.470 に答える
63

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

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

必要なコンテキストを選択するだけです。

于 2012-09-12T19:57:52.480 に答える
19

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

精度の問題について:最初にに保存47.48し、次にそこからdouble c新しいものを作成します。精度の低下は、に割り当てることです。あなたができるBigDecimaldoublec

BigDecimal b = new BigDecimal("47.48")

精度を失わないようにするため。

于 2012-09-12T20:00:22.913 に答える
6

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

Double.toString()doubles をStrings に変換する は、入力の正確な 10 進数値を出力しませx。 が double 値の場合、出力した値にx最も近い桁数を正確に出力しdoubleます。

ポイントは、正確に 47.48などというものがないということです。doubleDouble は値を 10 進数ではなく 2 進数として格納するため、正確な 10 進数値を格納できません。(そのBigDecimalためです!)

于 2012-09-12T20:07:44.770 に答える
3

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
于 2013-03-07T07:50:53.480 に答える