- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
当我用HALF_EVEN模式对双数取整时,发现一个问题,不知道是不是JDK的bug?请看下面的代码:
public static void main(String[] args) {
RoundingMode mode = RoundingMode.HALF_EVEN;
for (int i = 10; i < 100; i++) {
double d = i + 0.55;
int scale = 1;
process(d, scale++, mode);
d = i + 0.555;
process(d, scale++, mode);
d = i + 0.5555;
process(d, scale++, mode);
d = i + 0.55555;
process(d, scale++, mode);
System.out.println("\n");
}
}
private static void process(double d, int scale, RoundingMode roundingMode) {
BigDecimal b = new BigDecimal(d).setScale(scale, roundingMode);
System.out.println(d + " -> " + b);
}
我期望输出:
10.55 -> 10.6
10.555 -> 10.56
10.5555 -> 10.556
10.55555 -> 10.5556
11.55 -> 11.6
11.555 -> 11.56
11.5555 -> 11.556
11.55555 -> 11.5556
.....
但实际上,它输出的数据如下:
10.55 -> 10.6
10.555 -> 10.55
10.5555 -> 10.556
10.55555 -> 10.5556
11.55 -> 11.6
11.555 -> 11.55
11.5555 -> 11.556
11.55555 -> 11.5556
....
30.55 -> 30.6
30.555 -> 30.55
30.5555 -> 30.555
30.55555 -> 30.5556
31.55 -> 31.6
31.555 -> 31.55
31.5555 -> 31.555
31.55555 -> 31.5556
32.55 -> 32.5
32.555 -> 32.55
32.5555 -> 32.556
32.55555 -> 32.5555
33.55 -> 33.5
33.555 -> 33.55
33.5555 -> 33.556
33.55555 -> 33.5555
.........
62.55 -> 62.5
62.555 -> 62.55
62.5555 -> 62.556
62.55555 -> 62.5555
63.55 -> 63.5
63.555 -> 63.55
63.5555 -> 63.556
63.55555 -> 63.5555
64.55 -> 64.5
64.555 -> 64.56
64.5555 -> 64.555
64.55555 -> 64.5555
65.55 -> 65.5
65.555 -> 65.56
65.5555 -> 65.555
65.55555 -> 65.5555
66.55 -> 66.5
66.555 -> 66.56
66.5555 -> 66.555
66.55555 -> 66.5555
在JDK 1.7/1.8中有相同的结果
是不是JDK的bug?
最佳答案
不幸的是,这是生活的一部分,而且由于 double
类型在内部实现时基数为 2。对于科学编程来说,这是一件非常聪明的事情。但这确实意味着当您想查看或指定以 10 为基数的它们时,所见未必是所见。
例如,文字 10.555
实际上是一个略小于此的数字(10.5549999999999997157829056959599256515502929687...
)所以明显的德国四舍五入实际上会将这个数字向下舍入 。你的问题中有很多类似的案例。
这本身并不是一个错误,但如果您需要精确舍入,那么您应该使用一个类来以任意精度表示十进制数。
使用 BigDecimal
是一种选择,但您严重滥用它!。通过使用 double
的构造函数(即 new BigDecimal(d)
),d
中特有的不精确性只会被复制到 BigDecimal
。因此,您应该改用 String
中的构造函数,或使用类似的方法。
最后看看http://www.exploringbinary.com/floating-point-converter .输入您的十进制数,然后查看它在转换为 float 时采用的值。
关于java - Java RoundingMode.HALF_EVEN 是错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38263415/
我的 Java println 语句中有以下代码行: System.out.println("Iteration: " + counter + "\tRoot: " + new
这个问题已经有答案了: Is floating point math broken? (33 个回答) 已关闭 5 年前。 所以我有这个代码 public String getRounded(doub
像这样制作我自己的格式化程序: enum Formatters { enum Number { static let moneyFormatter: NumberFormatter = {
请随意评论我。下面的程序出了什么问题。它给出了不同的回合结果。 public class Test { public static String round(double value, int
据我了解,RoundingMode.HALF_UP 使用我们传统的舍入方式。但是,它没有给我想要的结果: 我正在使用具有不同参数(#、#.#、...等)的 DecimalFormat() 并输入 do
我编写此代码是为了测试 BigDecimal 的运行情况,但发现 RoundingMode.UNNECESSARY 引发了异常。谁能解释一下为什么? public class TestRounding
我正在尝试编写一个程序,该程序使用牛顿法计算用户提供的指定精度 (k) 的整数 (n) 的平方根。该程序运行良好,但我注意到我认为是一个舍入问题。有人可以帮我解决这个问题吗? 例如: 对于输入:n =
基于this stackoverflow post ,我希望以下内容打印出 0.59 而不是 0.60。 import java.math.RoundingMode; import java.text
我认为它返回1.13,但freemarker返回1.12。 什么是正确的? ${(1.125)?string(",##0.00;roundingMode=HALF_UP")} freemarker 版
这个问题已经有答案了: Java BigDecimal setScale and rounding with half_even (1 个回答) 已关闭 6 年前。 我正在尝试调试 HALF_EVEN
为什么这个 DecimalFormat 没有按预期使用 RoundingMode.HALF_UP 进行舍入,应该怎么做才能获得预期的输出?可以用 DecimalFormat 来完成吗? Decimal
我在四舍五入时遇到问题。具体来说,在阅读了所有 javadoc 之后,我期待以下代码: int n = (integer between 0 and 9, included) new BigDecim
当我这样做时: let a = self.oddsNumberFormatter.stringFromNumber(2.601) // 2.60 let b = self.oddsNumberForm
当我用HALF_EVEN模式对双数取整时,发现一个问题,不知道是不是JDK的bug?请看下面的代码: public static void main(String[] args) { Roun
看来 HALF_EVEN 舍入模式在 Java DecimalFormat 中的工作方式与 BigDecimal 不同。有没有办法使 DecimalFormat 保持一致? // Using BigD
目前我正在编写一个程序来计算数学常数。但是,我在舍入 BigDecimal 时遇到问题。一旦达到非终止小数 (1.6),就会抛出错误。我认为问题在于舍入线,但它也将其设置为正确的小数位数,但没有舍入它
我有大约 400 个使用 RoundingMode.HALF_UP 的语句,并且根据应用的性质,我希望用户能够在舍入模式之间进行选择。但是,如果可能的话,我不知道如何将其表示为变量。由于语句数量令人难
每当有十进制值时,我都试图四舍五入一个 Double 数字。我正在尝试以下。 以下代码段按预期四舍五入所有其他值。 1.08 -> 2 9.5 -> 10 但是将 0.08 舍入为 0 而不是 1。我
如何在 BigDecimal 中的点后只保留 3 个值? 我找到了一个解决方案,但它需要一个 RoundingMode BigDecimal d = BigDecimal.valueOf(0.
RoundingMode.HALF_EVEN 的 javadoc 指出: This rounding mode is analogous to the rounding policy used for
我是一名优秀的程序员,十分优秀!