有人可以向我解释为什么以下代码:
public class Test {
public static void main(String... args) {
round(6.2088, 3);
round(6.2089, 3);
}
private static void round(Double num, int numDecimal) {
System.out.println("BigDecimal: " + new BigDecimal(num).toString());
// Use Locale.ENGLISH for '.' as decimal separator
NumberFormat nf = NumberFormat.getInstance(Locale.ENGLISH);
nf.setGroupingUsed(false);
nf.setMaximumFractionDigits(numDecimal);
nf.setRoundingMode(RoundingMode.HALF_UP);
if(Math.abs(num) - Math.abs(num.intValue()) != 0){
nf.setMinimumFractionDigits(numDecimal);
}
System.out.println("Formatted: " + nf.format(num));
}
}
Run Code Online (Sandbox Code Playgroud)
给出以下输出?
[me@localhost trunk]$ java Test
BigDecimal: 6.208800000000000096633812063373625278472900390625
Formatted: 6.209
BigDecimal: 6.208899999999999863575794734060764312744140625
Formatted: 6.208
Run Code Online (Sandbox Code Playgroud)
如果你没有看到它:"6.2089"四舍五入到3位给出输出"6.208"而"6.2088"给出"6.209"作为输出.少即是多?
使用Java 5,6或7时结果很好但是这个Java 8给了我这个奇怪的输出.Java版本:
[me@localhost trunk]$ java -version
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) Server VM (build 25.5-b02, mixed mode)
Run Code Online (Sandbox Code Playgroud)
编辑:这是Java 7的输出:
[me@localhost trunk]$ java Test
BigDecimal: 6.208800000000000096633812063373625278472900390625
Formatted: 6.209
BigDecimal: 6.208899999999999863575794734060764312744140625
Formatted: 6.209
Run Code Online (Sandbox Code Playgroud)
Java 7版本:
[me@localhost trunk]$ java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) Server VM (build 24.51-b03, mixed mode)
Run Code Online (Sandbox Code Playgroud)
Hol*_*ger 19
我可以将这个问题追溯到java.text.DigitList第522行.
情况是,它认为十进制数字6.0289已经四舍五入(与等效BigDecimal表示相比,这是正确的6.208899…)并且决定不再向上舍入.问题是这个决定只有在四舍五入产生的数字的情况下才有意义5,而不是在它大于的情况下5.请注意代码如何HALF_DOWN正确区分digit=='5'和digit>'5'案例.
显然,这是一个错误,并且是一个奇怪的错误,因为执行类似权限的代码(仅针对另一个方向)正好在破坏的代码之下.
case HALF_UP:
if (digits[maximumDigits] >= '5') {
// We should not round up if the rounding digits position is
// exactly the last index and if digits were already rounded.
if ((maximumDigits == (count - 1)) &&
(alreadyRounded))
return false;
// Value was exactly at or was above tie. We must round up.
return true;
}
break;
case HALF_DOWN:
if (digits[maximumDigits] > '5') {
return true;
} else if (digits[maximumDigits] == '5' ) {
if (maximumDigits == (count - 1)) {
// The rounding position is exactly the last index.
if (allDecimalDigits || alreadyRounded)
/* FloatingDecimal rounded up (value was below tie),
* or provided the exact list of digits (value was
* an exact tie). We should not round up, following
* the HALF_DOWN rounding rule.
*/
return false;
else
// Value was above the tie, we must round up.
return true;
}
// We must round up if it gives a non null digit after '5'.
for (int i=maximumDigits+1; i<count; ++i) {
if (digits[i] != '0') {
return true;
}
}
}
break;
Run Code Online (Sandbox Code Playgroud)
这不会发生在另一个数字上的原因是,这6.2088不是四舍五入的结果(再次,与BigDecimal输出相比6.208800…).因此,在这种情况下,它将向上舍入.
| 归档时间: |
|
| 查看次数: |
4276 次 |
| 最近记录: |