本文介紹了從Java方法返回時,BigDecimal不保留實際值的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!
問題描述
我正在用Java制作一個貨幣轉(zhuǎn)換應(yīng)用程序。其他一些很棒的StackOverflwians給了我一些建議,讓我仔細閱讀BigDecimal,以便替換Double來解決任何精度問題。
我有一個兩種方法系統(tǒng);它從起始貨幣轉(zhuǎn)換為美元,然后將美元值轉(zhuǎn)換為目標貨幣。
注意,我的轉(zhuǎn)換率存儲如下:
// 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替換了我的替身之后,我決定測試一下,看看結(jié)果如何。
我的測試程序類運行以下方法以啟動轉(zhuǎn)換過程。
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;
}
當(dāng)我輸入我的示例變量(將2.78日圓轉(zhuǎn)換為加拿大元)時,我逐步執(zhí)行了該過程,并發(fā)現(xiàn)在我返回值之前,一切都在運行。
從前面提到的方法中,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);
}
所有值都正確傳入,逐步執(zhí)行到正確的大小寫(“Yen”),變量窗格顯示”FromQuantity”BigDecimal的intCompt值為278(這對我來說很有意義)
一旦斷點返回到”Convert”方法,它就會變得一團糟。它返回的不是2.78 * 0.008853 = 0.0246
,而是-9223372036854775808
。
這會導(dǎo)致生成所有其他計算并出錯。
我剛開始使用BigDecimal,所以我可能犯了一個很明顯的錯誤;但我很高興學(xué)習(xí),所以我征求了你們的建議:)
感謝任何幫助。
推薦答案
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
類的要點是為了避免floating-point技術(shù)中的inherent inaccuracies。浮點類型,如float
/Float
和double
/Double
以精度換取執(zhí)行速度。相比之下,BigDecimal
速度較慢,但很準確。
您的代碼:
new BigDecimal( 0.76135 )
new BigDecimal( 1.1345 )
new BigDecimal( 0.008853 )
…正在傳遞double
基元文本。在編譯過程中,您鍵入的文本0.76135
被解析為一個數(shù)字,特別是double
(一個64位浮點值)。在這一點上,您引入了這種類型固有的不準確性。換句話說,從0.76135
產(chǎn)生的double
可能不再是確切的0.76135
。
我們在實例化后立即轉(zhuǎn)儲您的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
因此,通過創(chuàng)建double
數(shù)值,您調(diào)用了浮點技術(shù),并引入了不準確性。
使用字符串
解決方案?使用字符串,完全避免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
接下來,您應(yīng)該學(xué)習(xí)BigDecimal
的舍入和截斷。已多次涉及堆棧溢出。
這篇關(guān)于從Java方法返回時,BigDecimal不保留實際值的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,