54

私は次のことを試みました、

   double doubleVal = 1.745;
   double doubleVal1 = 0.745;
   BigDecimal bdTest = new BigDecimal(  doubleVal);
   BigDecimal bdTest1 = new BigDecimal(  doubleVal1 );
   bdTest = bdTest.setScale(2, BigDecimal.ROUND_HALF_UP);
   bdTest1 = bdTest1.setScale(2, BigDecimal.ROUND_HALF_UP);
   System.out.println("bdTest:"+bdTest); //1.75
   System.out.println("bdTest1:"+bdTest1);//0.74    problemmmm ????????????  

しかし、奇妙な結果が得られました。なんで?

4

6 に答える 6

107

floatまたはdoubleからBigDecimalsを作成しないでください。intまたはstringsからそれらを構築します。浮き、緩い精度を2倍にします。

このコードは期待どおりに機能します(タイプをdoubleからStringに変更しました)。

public static void main(String[] args) {
  String doubleVal = "1.745";
  String doubleVal1 = "0.745";
  BigDecimal bdTest = new BigDecimal(  doubleVal);
  BigDecimal bdTest1 = new BigDecimal(  doubleVal1 );
  bdTest = bdTest.setScale(2, BigDecimal.ROUND_HALF_UP);
  bdTest1 = bdTest1.setScale(2, BigDecimal.ROUND_HALF_UP);
  System.out.println("bdTest:"+bdTest); //1.75
  System.out.println("bdTest1:"+bdTest1);//0.75, no problem
}
于 2012-09-17T13:45:37.143 に答える
13
double doubleVal = 1.745;
double doubleVal1 = 0.745;
System.out.println(new BigDecimal(doubleVal));
System.out.println(new BigDecimal(doubleVal1));

出力:

1.74500000000000010658141036401502788066864013671875
0.74499999999999999555910790149937383830547332763671875

これは、2つのダブルの実際の値を示し、得られる結果を説明しています。他の人が指摘しているように、doubleコンストラクターは使用しないでください(doubleの実際の値を確認したい特定の場合を除いて)。

倍精度の詳細:

于 2012-09-17T13:48:42.677 に答える
10

BigDecimal.valueOf(double d)の代わりに使用してくださいnew BigDecimal(double d)。最後のものはfloatとdoubleによる精度エラーがあります。

于 2014-08-12T16:03:32.073 に答える
3

これにより、何が悪かったのかについてのヒントが得られるかもしれません。

import java.math.BigDecimal;

public class Main {
    public static void main(String[] args) {
        BigDecimal bdTest = new BigDecimal(0.745);
        BigDecimal bdTest1 = new BigDecimal("0.745");
        bdTest = bdTest.setScale(2, BigDecimal.ROUND_HALF_UP);
        bdTest1 = bdTest1.setScale(2, BigDecimal.ROUND_HALF_UP);
        System.out.println("bdTest:" + bdTest); // prints "bdTest:0.74"
        System.out.println("bdTest1:" + bdTest1); // prints "bdTest:0.75"
    }
}

問題は、入力(a double x=0.745;)が0.745を正確に表すことができないことです。実際には、わずかに低い値が保存されます。の場合BigDecimals、これはすでに0.745を下回っているため、切り捨てられます...

BigDecimal(double/float)コンストラクターを使用しないようにしてください。

于 2012-09-17T13:45:15.677 に答える
2

あなたの興味のために、同じことをするdouble

double doubleVal = 1.745;
double doubleVal2 = 0.745;
doubleVal = Math.round(doubleVal * 100 + 0.005) / 100.0;
doubleVal2 = Math.round(doubleVal2 * 100 + 0.005) / 100.0;
System.out.println("bdTest: " + doubleVal); //1.75
System.out.println("bdTest1: " + doubleVal2);//0.75

あるいは単に

double doubleVal = 1.745;
double doubleVal2 = 0.745;
System.out.printf("bdTest: %.2f%n",  doubleVal);
System.out.printf("bdTest1: %.2f%n",  doubleVal2);

両方の印刷

bdTest: 1.75
bdTest1: 0.75

私はコードをできるだけシンプルに保つことを好みます。;)

@mshutovが指摘しているように、半分の値が常に切り上げられるようにするには、もう少し追加する必要があります。これは、のような数値265.335が表示よりも少し少ないためです。

于 2012-09-17T14:00:05.873 に答える
0

次のようなさまざまなオプションを利用できます。

 Double d= 123.12;
BigDecimal b = new BigDecimal(d, MathContext.DECIMAL64); // b = 123.1200000
b = b.setScale(2, BigDecimal.ROUND_HALF_UP);  // b = 123.12

BigDecimal b1 =new BigDecimal(collectionFileData.getAmount(), MathContext.DECIMAL64).setScale(2, BigDecimal.ROUND_HALF_UP)  // b1= 123.12

 d = (double) Math.round(d * 100) / 100;
BigDecimal b2 = new BigDecimal(d.toString());  // b2= 123.12



于 2020-07-30T15:33:15.827 に答える