Javaメソッドから返されるときのBigDecimalは、実際の値を保っていません

ブライアン・ダグラス:

私はJavaで通貨換算アプリを作っています。他のいくつかの素晴らしいStackOverflowiansは私に任意の精度の問題を修正するために、二重の交換を目的としてBigDecimalの上に読み込むためのアドバイスを与えました。

私は2つの方法でシステムを持っています。それはUSDに起動通貨から変換場合、宛先通貨にUSD値を変換します。

注、私のコンバージョン率は、次のように格納されます。

// Conversion Rates - START (as of October 30, 2018 @ 3:19 AM)
// Rates obtained from exchange-rates.org

//Convert to United States Dollar rates
private final BigDecimal CAD_TO_USD = new BigDecimal(0.76135);
private final BigDecimal EUR_TO_USD = new BigDecimal(1.1345);
private final BigDecimal YEN_TO_USD = new BigDecimal(0.008853);
// Conversion Rates - END

私は、それぞれのBigDecimalと私のダブルスを交換した後 - 私はそれをテストし、それがすべてうまくいく方法を確認することにしました。

私のテスタークラスには、変換プロセスを開始するには、次の方法を実行します。

public BigDecimal convert()
{
    BigDecimal value;

    value = convertToUSD(); //Converts the current currency into USD 
    value = convertFromUSD(value);  //Converts the previous USD currency value into the destination currency

    return value;
}

私は(カナダドルに2.78円を変換している)私のサンプル変数を入力すると、私は、プロセスを通じて段階と、私は値を返すまで、そのすべての機能をアップしました。

前述の方法から、convertToUSD()実行されると、次のようにコーディングされています

private BigDecimal convertToUSD()
{
    switch (fromCurrency)
    {
        case "USD":
            return fromQuantity.multiply(new BigDecimal(1));

        case "CAD":
            return fromQuantity.multiply(CAD_TO_USD);

        case "EUR":
            return fromQuantity.multiply(EUR_TO_USD);

        case "YEN":
            return fromQuantity.multiply(YEN_TO_USD);
    }

    return new BigDecimal(0);
}

すべての値が正しく渡され、それが適切な場合(「円」)へのダウンを通じて段階的に説明し、「fromQuantity」のBigDecimalは(私には理にかなって)278のintCompact値を持っていることを、変数ペインショー

ここでは、画像の説明を入力します。

すぐにブレークポイントを返しますが、「変換」方法にバックアップとして、それはすべてが台無しになります。代わりに返す2.78 * 0.008853 = 0.0246、それが返されます-9223372036854775808

ここでは、画像の説明を入力します。

これは、生産とエラーに他のすべての計算が発生します。

私はBigDecimalの使用に新しいですので、私は完全に明白な間違いを犯してすることができます。私は学ぶことが幸せですので、私はあなたたちからアドバイスを求め:)

どのような援助が理解されます。

バジルボーク:

TL; DR

使用することはString、ありませんdoubleリテラル。

new BigDecimal( "2.78" )           // Pass "2.78" not 2.78
.multiply(
    new BigDecimal( "0.008853" )   // Pass "0.008853" not 0.008853
)
.toString()

0.02461134

浮動小数点型を渡さないでください

ポイントBigDecimalクラスは避けることである固有の不正確で見つかった浮動小数点テクノロジを。浮動小数点型などのfloat/ Floatdouble/ Double実行速度精度を離れて取引。これとは対照的に、BigDecimalゆっくりではあるが正確です。

あなたのコード:

new BigDecimal( 0.76135 )
new BigDecimal( 1.1345 )
new BigDecimal( 0.008853 )

...通過しているdoubleプリミティブリテラルを。コンパイル時には、あなたが入力したテキストは0.76135、具体的として、数として解析されdouble(64ビット浮動小数点値)。その時点で、このタイプの固有の不正確を導入しています。言い換えると、doubleから生産は0.76135もはや正確にないかもしれません0.76135

さんがあなたのダンプしてみましょうBigDecimalすぐにインスタンス化した後にインスタンスを。

System.out.println( new BigDecimal( 0.76135 ) );    // Passing a `double` primitive.
System.out.println( new BigDecimal( 1.1345 ) );
System.out.println( new BigDecimal( 0.008853 ) );

0.7613499999999999712230192017159424722194671630859375

1.13450000000000006394884621840901672840118408203125

0.0088529999999999997584154698415659368038177490234375

だから、作成することにより、double数値を、あなたは、浮動小数点の技術を呼び出し、および不正確さを紹介しました。

使用文字列

ソリューション?回避文字列での作業、double完全にタイプを。

いくつか入れてこれらの入力の周りに二重引用符を、そして出来上がり

System.out.println( new BigDecimal( "0.76135" ) );  // Passing a `String` object.
System.out.println( new BigDecimal( "1.1345" ) );
System.out.println( new BigDecimal( "0.008853" ) );

0.76135

1.1345

0.008853

あなたは期待しました2.78 * 0.008853 = 0.0246試してみよう。

BigDecimal x = new BigDecimal( "2.78" );
BigDecimal y = new BigDecimal( "0.008853" );
BigDecimal z = x.multiply( y );
System.out.println( x + " * " + y + " = " + z );

2.78 * 0.008853 = 0.02461134

次は丸め&と切り捨て上に勉強しなければなりませんBigDecimalすでにスタックオーバーフローに何度もカバーしました。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=185737&siteId=1