![](/img/trans.png)
[英]MathContext.DECIMAL32 vs MathContext.DECIMAL64, which one to use, and why?
[英]Use of java.math.MathContext
最近我嘗試了解java.math.MathContext的使用但未能正確理解。 它是否用於java.math.BigDecimal
舍入。 如果是,為什么不繞十進制數字,甚至是尾數部分。
從API文檔中,我發現它遵循ANSI X3.274-1996
和ANSI X3.274-1996/AM 1-2000
ANSI X3.274-1996
規范中指定的標准,但我沒有讓它們在線閱讀。
如果您對此有任何想法,請告訴我。
要僅舍入BigDecimal的小數部分,請查看BigDecimal.setScale(int newScale, int roundingMode)
方法。
例如,將小數點后的三位數字更改為兩位數的數字,並向上舍入:
BigDecimal original = new BigDecimal("1.235");
BigDecimal scaled = original.setScale(2, BigDecimal.ROUND_HALF_UP);
結果是BigDecimal值為1.24(因為舍入規則)
@jatan
謝謝你的回答。 這說得通。 你能否在BigDecimal#round方法的上下文中解釋我的MathContext。
BigDecimal.round()
與任何其他BigDecimal
方法沒有什么特別之處。 在所有情況下, MathContext
指定有效位數和舍入技術。 基本上,每個MathContext
都有兩個部分。 有一個精度,還有一個RoundingMode
。
精度再次指定有效位數。 因此,如果您將123
指定為數字,並要求2位有效數字,那么您將獲得120
。 如果從科學記數的角度思考,可能會更清楚。
科學記數法中123
為1.23e2
。 如果您只保留2位有效數字,那么您將獲得1.2e2
或120
。 通過減少有效位數,我們降低了指定數字的精度。
RoundingMode
部分指定了我們應該如何處理精度損失。 要重復使用該示例,如果使用123
作為數字,並要求2位有效數字,則會降低精度。 使用RoundingMode
為HALF_UP
(默認模式), 123
將變為120
。 使用CEILING
的RoundingMode
,你將得到130
。
例如:
System.out.println(new BigDecimal("123.4",
new MathContext(4,RoundingMode.HALF_UP)));
System.out.println(new BigDecimal("123.4",
new MathContext(2,RoundingMode.HALF_UP)));
System.out.println(new BigDecimal("123.4",
new MathContext(2,RoundingMode.CEILING)));
System.out.println(new BigDecimal("123.4",
new MathContext(1,RoundingMode.CEILING)));
輸出:
123.4
1.2E+2
1.3E+2
2E+2
您可以看到精度和舍入模式都會影響輸出。
我想在這里添加一些例子。 我沒有在之前的答案中找到它們,但我發現它們對於那些可能誤導有效 小數 位數的人有用。 我們假設,我們有這樣的背景:
MathContext MATH_CTX = new MathContext(3, RoundingMode.HALF_UP);
對於此代碼:
BigDecimal d1 = new BigDecimal(1234.4, MATH_CTX);
System.out.println(d1);
很明顯,你的結果是1.23E+3
,如上所述。 首字母是123 ...
但在這種情況下:
BigDecimal d2 = new BigDecimal(0.000000454770054, MATH_CTX);
System.out.println(d2);
你的號碼在逗號后不會四舍五入 - 對某些人來說,這可能不直觀,值得強調。 相反,它將四舍五入到前3位有效數字 ,在本例中為“4 5 4”。 所以上面的代碼導致4.55E-7
而不是0.000
正如有人所期望的那樣。
類似的例子:
BigDecimal d3 = new BigDecimal(0.001000045477, MATH_CTX);
System.out.println(d3); // 0.00100
BigDecimal d4 = new BigDecimal(0.200000477, MATH_CTX);
System.out.println(d4); // 0.200
BigDecimal d5 = new BigDecimal(0.000000004, MATH_CTX);
System.out.println(d5); //4.00E-9
我希望這顯而易見,但相關的例子會有所幫助......
如果我正確理解你,聽起來好像你期望MathContext控制小數點后應該保留多少位數。 這不是它的用途。 它指定要保留的位數, 總數 。 因此,如果您指定需要3位有效數字,那就是您要獲得的所有數字。
例如,這個:
System.out.println(new BigDecimal("1234567890.123456789",
new MathContext(20)));
System.out.println(new BigDecimal("1234567890.123456789",
new MathContext(10)));
System.out.println(new BigDecimal("1234567890.123456789",
new MathContext(5)));
將輸出:
1234567890.123456789
1234567890
1.2346E+9
這不是為了好玩。 實際上我找到了一些在線示例,其中說明了使用MathContext
來舍入存儲在BigDecimal中的金額/數字。
例如,
如果MathContext
配置為具有precision = 2
和rounding mode = ROUND_HALF_EVEN
BigDecimal Number = 0.5294
, 舍入為0.53
所以我認為這是一種更新的技術並用它來進行舍入。 然而它變成了噩夢,因為它甚至開始繞過數字的一部分。
例如,
Number = 1.5294
舍入為1.5
Number = 10.5294
舍入為10
Number = 101.5294
舍入為100
.... 等等
所以這不是我期望的舍入行為(因為精度= 2)。
它似乎有一些邏輯,因為從模式我可以說它需要數字的前兩位(精度是2)然后追加0直到no。 數字與未包含的數量相同(結帳101.5294的例子...)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.