4

BigDecimalクラスに新しいグレードの丸めを実装しようとしていますが、バグが発生している可能性があります。おそらく何か間違ったことをしているに違いありません。以下のコードは私の問題を明らかにします:

public static void main(String[] args) throws IOException {
    BigDecimal valDouble = new BigDecimal(0.35);
    valDouble = valDouble.setScale(1, BigDecimal.ROUND_HALF_UP);
    System.out.println(valDouble.doubleValue()); // prints 0.3

    BigDecimal valString = new BigDecimal(new String("0.35"));
    valString = valString.setScale(1, BigDecimal.ROUND_HALF_UP);
    System.out.println(valString.doubleValue()); // prints 0.4
}

ここでの私の疑問は、BigDecimalはdoubleコンストラクターとStringコンストラクターで異なるのかということです。

私はこの「バグ」を理解できません。少なくとも、以下のように、単純な文字列連結を使用して「解決」しました。

BigDecimal valDouble = new BigDecimal("" + 0.35);

何がこの奇妙な振る舞いを引き起こしているのか考えてみませんか?

4

3 に答える 3

9

これはバグではありません。ダブルリテラルとしての0.35は、0.35と正確に等しくない値を表します。0.349999995か何かのようなものである可能性があります。したがって、切り捨てられます。

Stringコンストラクターを使用すると、「0.35」を使用して0.35を正確に指定でき、切り上げられます。

doubleここではコンストラクターを使用しないでください。使用するのに十分重要な場合BigDecimalは、浮動小数点の土地に近づかないようにする必要があります。

于 2012-07-06T19:28:24.407 に答える
5

0.35が何として表されているかを推測する必要はありません

BigDecimal valDouble = new BigDecimal(0.35);
System.out.println(valDouble);

プリント

0.34999999999999997779553950749686919152736663818359375

これは、小数点以下1桁に0.3として切り捨てられます。

文字列に変換する必要はありません、あなたは使用することができますvalueOf

BigDecimal valDouble = BigDecimal.valueOf(0.35);
System.out.println(valDouble);

プリント

0.35

半分を小数点以下1桁に切り上げるには、次を使用できます。

double d = 0.35;
double d1 = Math.round(d * 10) / 10.0;
System.out.println(d1);

プリント

0.4
于 2012-07-06T20:37:16.453 に答える
0

0.35はすでに不正確であり、FPの2進基数になりました。基数が10進数であるため、正確な新しいBigDecimal( "0.35")を使用します。

于 2012-07-07T02:58:10.287 に答える