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