2017-08-13 64 views
1

我正在尋找一種精確的方法來在Java中乘以兩個浮點數,並且我讀到應該使用BigDecimal,但它不能按預期工作。我究竟做錯了什麼?在Java中精確地乘以兩個數字

我的代碼:

BigDecimal a = new BigDecimal(3.53); 
BigDecimal b = new BigDecimal(3.59); 
BigDecimal c = a.multiply(b); 

System.out.println(c); 

結果:

12.672699999999998796873512674210388041622697702955394242845497954075284496866515837609767913818359375 

預期結果:

12.6727 
+4

您應該嘗試打印'a'和'b'。 –

+1

我看到它是相同的結果,預期的結果是上述值的一些四捨五入的值,您可以使用** Math.round ** –

+0

之類的東西在開始的時候,浮點常量並不精確。必須深刻理解。 –

回答

12

當您使用BigDecimal(double)構造它不能超過double更精確,使用String形式代替。像,

BigDecimal a = new BigDecimal("3.53"); 
BigDecimal b = new BigDecimal("3.59"); 
BigDecimal c = a.multiply(b); 
System.out.println(c); 

,輸出

12.6727 

鏈接的Javadoc中說,在部分 -

注:

  1. 此構造方法的結果有一定的不可預知的。有人可能會認爲在Java中編寫新的BigDecimal(0.1)將創建一個BigDecimal,該值等於0.1(非縮放值爲1,刻度爲1),但實際上它等於0.1000000000000000055511151231257827021181583404541015625。這是因爲0.1不能完全表示爲double(或者就此而言,作爲任何有限長度的二進制分數)。因此,傳遞給構造函數的值並不完全等於0.1,儘管如此。

  2. String構造,在另一方面,是完全可以預測的:寫new BigDecimal("0.1")創建的BigDecimal是恰好等於0.1,正如人們所期望。因此,通常建議優先使用String constructor

+0

如何使用「BigDecimal a = BigDecimal」。的valueOf(3.53d);」 ? 這樣,我可以使用一個實際的雙變量,而不是將其轉換爲字符串,並仍然保留精度 – Mikemike

+0

@Mikemike這仍然是一個壞主意。首先使用雙打是個問題。使用字符串和BigDecimal之間沒有觸及雙打。如果你使用這個方法的數字太精確到兩倍,你仍然會得到錯誤的結果。 –

+0

@Louis Wasserman不知何故,我得到了正確的結果: BigDecimal a = BigDecimal.valueOf(3.53d); BigDecimal b = BigDecimal.valueOf(3.59d); BigDecimal c = a.multiply(b); \t \t System.out.println(c); // 12.6727 – Mikemike