![](/img/trans.png)
[英]Why doesn't java.math.RoundingMode come with HALF_ODD rounding?
[英]how does java.math.RoundingMode work?
我在四舍五入時遇到問題。 具體來說,在閱讀了所有 javadoc 之后,我期待以下代碼:
int n = (integer between 0 and 9, included)
new BigDecimal(n + 0.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
返回n + 0.56
。 相反,這些是n
從0
到4
的返回值:
new BigDecimal(0.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
0.56
new BigDecimal(1.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
1.55
new BigDecimal(2.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
2.56
new BigDecimal(3.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
3.56
new BigDecimal(4.555d).setScale(2, RoundingMode.HALF_UP).doubleValue()
4.55
我還嘗試更改舍入模式:
int n = (integer between 0 and 9, included)
new BigDecimal(n + 0.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
期望n + 0.55
作為每個n
的結果。 相反,返回值與前面的示例完全相同:
new BigDecimal(0.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
0.56
new BigDecimal(1.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
1.55
new BigDecimal(2.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
2.56
new BigDecimal(3.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
3.56
new BigDecimal(4.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue()
4.55
我錯過了什么嗎?
你遇到的問題是 double 不是一個精確的表示,你是基於這個不精確的數字進行舍入的。
BigDecimal bd = new BigDecimal(1.555d);
System.out.println("bd=" + bd);
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println("after rounding bd=" + bd);
double d = bd.doubleValue();
System.out.println("after rounding d=" + d);
印刷
bd=1.5549999999999999378275106209912337362766265869140625
after rounding bd=1.55
after rounding d=1.55
然而
BigDecimal bd = BigDecimal.valueOf(1.555d);
System.out.println("bd=" + bd);
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println("after rounding bd=" + bd);
double d = bd.doubleValue();
System.out.println("after rounding d=" + d);
印刷
bd=1.555
after rounding bd=1.56
after rounding d=1.56
這是有效的,因為BigDecimal.valueOf
會根據打印時出現的 double 情況進行一些額外的舍入。
但是,除非性能/簡單性不是問題,否則我不會使用 BigDecimal。
double d = 1.555d;
System.out.println("d=" + d);
d = roundToTwoPlaces(d);
System.out.println("after rounding d=" + d);
public static double roundToTwoPlaces(double d) {
return ((long) (d < 0 ? d * 100 - 0.5 : d * 100 + 0.5)) / 100.0;
}
印刷
d=1.555
after rounding d=1.56
詳細信息Double your money again比較不同四舍五入方式的性能。
@Peter Lawrey 我查看了您的示例並編寫了一個快速程序,比較了您發布的簡單方法以及 RoundingMode 的所有方法。 代碼在這里供任何感興趣的人使用,這將清楚地顯示差異:
[RoundingMode.java] https://gitlab.com/bobby.estey/java/-/blob/master/maven/jdk14/src/main/java/mathematics/RoundingModeExamples.java
Results:
lowDouble: 1.55553
simple - lowDouble: 1.5555
RoundingMode.UP - lowDouble: 1.5556
RoundingMode.DOWN - lowDouble: 1.5555
RoundingMode.CEILING - lowDouble: 1.5556
RoundingMode.FLOOR - lowDouble: 1.5555
RoundingMode.HALF_UP - lowDouble: 1.5555
RoundingMode.HALF_DOWN - lowDouble: 1.5555
RoundingMode.HALF_EVEN - lowDouble: 1.5555
highDouble: 1.55555
simple - highDouble: 1.5556
RoundingMode.UP - highDouble: 1.5556
RoundingMode.DOWN - highDouble: 1.5555
RoundingMode.CEILING - highDouble: 1.5556
RoundingMode.FLOOR - highDouble: 1.5555
RoundingMode.HALF_UP - highDouble: 1.5555
RoundingMode.HALF_DOWN - highDouble: 1.5555
RoundingMode.HALF_EVEN - highDouble: 1.5555
0.555d
是一個double
0.555d
值。 它可能略大於 0.555 或略小。
舍入模式用於舍入十進制值。
您可以使用。
double DecimalValue = 3.1452;
BigDecimal decimal = new BigDecimal(DecimalValue).setScale(2, RoundingMode.DOWN);
=>
RoundingMode.CEILING
向正無窮大舍入的舍入模式。 對於正值,此舍入模式表現為向上,對於負值表現為向下。 規則: x.round() >= x
RoundingMode.DOWN
值向零舍入的舍入模式。 規則: x.round().abs() <= x.abs()
RoundingMode.DOWN
向負無窮大舍入的舍入模式。 對於正值,此舍入模式表現為 DOWN,對於負值表現為 UP。 規則: x.round() <= x
RoundingMode.HALF_DOWN
舍入模式,其中值向最近的鄰居舍入。 通過四舍五入打破平局。
RoundingMode.HALF_EVEN
舍入模式,其中值向最近的鄰居舍入。 通過四舍五入到偶數鄰居來打破平局。
RoundingMode.HALF_UP
舍入模式,其中值向最近的鄰居舍入。 通過四舍五入打破平局。
RoundingMode.UNNECESSARY
舍入模式,其中舍入操作會在需要舍入的情況下引發ArithmeticException
,即無法准確表示值的情況。
RoundingMode.UP
舍入模式,正值向正無窮大舍入,負值向負無窮大舍入。 規則: x.round().abs() >= x.abs()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.