2013-07-21 57 views
0

我在Java中四捨五入BigDecimals時遇到了一些麻煩。 我想轉換從腳英寸,反之亦然值,這就是我:我該如何解決這個糟糕的BigDecimal舍入?

//To convert from ft to in; 
//... 
BigDecimal CINCH = new BigDecimal("12"); 
Inch.setText(CINCH.multiply(VFEET).toString()); //VFEET is the user input 

//To convert from in to ft 
//... 
BigDecimal CFEET = new BigDecimal("12"); //Initially I multiplied the input with 0.0833333333 
Feet.setText(VINCH.divide(CFEET, 7, RoundingMode.HALF_UP).toString()); //VINCH is the user input 

如果我嘗試將1-英尺英寸,它返回預期值(12)。 如果我嘗試將12英寸轉換爲英尺,它會返回預期值(1),但會出現像我預期的那樣的7個小數點後的情況。

如果我將1英寸轉換爲英尺,則返回0.08333333,如果將此值從英尺轉換爲英寸,則應該返回1,但返回0.9999996。 如果我將2英寸轉換爲英尺,則返回0.1666667,如果我將此值從英尺轉換爲英寸,則返回2.0000004

如何解決此問題? (我知道我可以用雙打做這個,這是我的第一個計劃,但我遇到了一個準確性問題(大於這個))

+0

怎麼樣擺脫四捨五入,即使用_RoundingMode.UNNECESSARY_? – Juvanis

+0

雙打實際上是測量的正確答案。小數應該用於具有精確數字量的事物,例如財務值。儘管它沒有專門解決您的問題,但請參閱http://ericlippert.com/2013/07/18/why-not-allow-doubledecimal-implicit-conversions。 – tvanfosson

+0

@Juvanis我嘗試使用RoundingMode.UNNECESSARY ...當我嘗試轉換時,程序崩潰...(我嘗試1英尺) – Luso

回答

0

雖然選擇什麼數據類型用於表示,但應該反映潛在的問題有待解決。一般來說,對於測量,您可以使用雙打,因爲測量的精度通常小於表示的精度。在這種情況下,表示中的錯誤不太重要。一般來說,您也可以處理兩個值之間的差異不符合表示精度的尺度相似的測量值。在你的情況下,看起來你需要比雙精度表示更高的精度,但不希望數字顯示精度允許的十進制數。

一個可能的解決方案是內部保持值比您顯示的精度更高。這將適用於任何類型,但可以很容易地用decimal的示例進行演示。例如(在C#)

decimal f = 1m; 
decimal i = f/12m; 

Console.WriteLine("{0} {1} {2} {3}", f, i, i * 12m, Math.Round(i * 12m, 7)); 

產生下面的輸出,你可以看到,通過提供較少的數字,我們得到 預期的應答

1 0.0833333333333333333333333333 0.9999999999999999999999999996 1.0000000 

我的建議是在較高的做算術精度和顯示精度較低。在您的情況下,您正在按照7的比例進行算術運算,因此您可能希望在輸出中最多顯示6位數字的精度,或者相反將比例設置得更高,以便您可以顯示與測量結果相同的精度數字。

您還可能有所幫助,Scale() of Divide method in BigDecimal