Java 为什么这个数字要向下舍入?
我对Java的Java 为什么这个数字要向下舍入?,java,double,number-formatting,Java,Double,Number Formatting,我对Java的NumberFormat的行为感到困惑 考虑以下方法,将双精度值转换为其百分比表示形式,并将结果百分比四舍五入到小数点后三位: public static String doubleToPercent(final double val) { NumberFormat nf = NumberFormat.getPercentInstance(); // Default rounding mode is HALF_EVEN nf.setRoundingMode(
NumberFormat
的行为感到困惑
考虑以下方法,将双精度值转换为其百分比表示形式,并将结果百分比四舍五入到小数点后三位:
public static String doubleToPercent(final double val) {
NumberFormat nf = NumberFormat.getPercentInstance();
// Default rounding mode is HALF_EVEN
nf.setRoundingMode(RoundingMode.HALF_UP);
nf.setMaximumFractionDigits(3);
return nf.format(val);
}
取整模式为向上取整
worksAsExpected
中的结果并不让我感到惊讶;测试通过:
@Test
public void worksAsExpected() {
double input = 1.234585;
String expected = "123.459%";
String output = doubleToPercent(input);
assertEquals(expected, output);
}
但是这个呢:
@Test
public void surprise() {
double input = 1.234535;
String expected = "123.454%";
String output = doubleToPercent(input);
assertEquals(expected, output);
}
为什么这个测试失败了?为什么1.234535
向下舍入而1.234585
向上舍入
另一方面,如果最后一位数字是6
,则数字将向上舍入
@Test
public void noSurprise() {
double input = 1.234536;
String expected = "123.454%";
String output = doubleToPercent(input);
assertEquals(expected, output);
}
这与双精度的限制有关吗?我猜像1.234535
这样的数字在double
的能力范围内
我使用的是运行Windows7x86的Java1.7.051
非常感谢您的帮助。这些数字是使用双精度浮点格式()存储的
我并不奇怪您会遇到精度方面的问题,不幸的是,Java中的double
并不是执行精确计算的非常可靠的方法。
这也是一个原因,因为对于数学模块,首选其他工具,如Matlab
无论如何,在您的示例中,您可以解决您的问题(希望)增加nf.setMaximumFractionDigits()中数字的数量代码>
或者,您可以根据需要切换到BigDecimal
或DecimalFormat
。1.234535=1.2345344999999993796961916814325374508514404296875作为双精度,将其四舍五入为1.23453
您可以使用我的十进制/二进制转换器来查看发生了什么
注:与普通二进制数不同,二进制分数的精确十进制表示始终具有相同的位数:
0.001 =
0.125,
0.1101101 =
0.8515625,
0.00001110101011 =
0.05731201171875,
1.0011110000001010011111000101101011000100011100011011 =
1.2345349999999999379696191681432537734508514404296875
etc.
如果您需要更多地控制小数点和四舍五入,则必须使用。请注意,最好计算对数字执行的每个操作的舍入误差 谢谢<代码>十进制格式
也会产生不正确的结果。但是我同意BigDecimal
是一条路要走。我对Matlab的评论感到困惑。Matlab和Java都使用IEEE 754 64位二进制浮点来表示双精度。您是否使用工具来获取该数字?@Matthias Braun是的。我使用了我的十进制/二进制转换器(),对于1.234535,它返回1.001111000000101001111100010110101100011100010110100011110…,它将53位舍入为1.001111000000101001111100010110110001110001011。然后我把它放入二进制到十进制的转换器中,得到1.234534499999999379696191681432537734508514404296875。(还有其他方法——可能更容易——来完成这项工作。)@Aaron Digulla这是一项相当繁重的编辑工作。删除评论、将评论移动到答案中并合并答案是正常的吗?不,但我的答案只是部分正确,你显然比我更了解这一点,而且评论中有太多有用的信息,我觉得我应该纠正这一点。这似乎是最好的解决办法。请随意改进我的编辑:-)我的主要反对意见是最后一段(关于BigDecimal)--我没有写。你能把这归咎于谁吗?谢谢