[英]DecimalFormat and rounding for fixed point numbers
在使用DecimalFormat
,我对使用定点模式舍入数字时的行为感到困惑。 为了使事情更具体:
double n = 2082809.080589735D;
// Output the exact value of n
System.out.println("value: " + new BigDecimal(n).toPlainString());
System.out.println("double: " + n);
DecimalFormat format = new DecimalFormat("0.00000000");
System.out.println("format: " + format.format(n));
System.out.println("format (BD): " + format.format(new BigDecimal(n)));
该代码段的输出为:
value: 2082809.080589734949171543121337890625
double: 2082809.080589735
format: 2082809.08058974
format (BD): 2082809.08058973
从第一条输出线,我们注意到实际值低于 2082809.08058973
和2082809.08058974
( ...49...
)之间的2082809.08058973
。 尽管如此, DecimalFormat
在提供double
参数时会向上DecimalFormat
该值。
其他值向下取整:
value: 261285.2738465850125066936016082763671875
double: 261285.273846585
format: 261285.27384658
format (BD): 261285.27384659
并非在所有情况下都会发生这种情况:
value: 0.080589734949171543121337890625
double: 0.08058973494917154
format: 0.08058973
format (BD): 0.08058973
value: 0.2738465850125066936016082763671875
double: 0.2738465850125067
format: 0.27384659
format (BD): 0.27384659
在我看来, double
的格式化字符串是根据基于Double.toString()
东西生成的不精确的十进制值使用半偶数舍入而舍入的,而不是所讨论的double
表示的实际数学值。 当格式化的精度非常接近(或超过) double
型提供的精度时,事情开始变得有些随机。
在上述所有情况下,格式化相应的BigDecimal
似乎都能按预期执行舍入。
在这种情况下,我找不到任何描述DecimalFormat
正确行为的规范。
此行为记录在某处吗?
从正确性的角度来看,四舍五入实际的数学值不是更好的选择吗?
我了解编写1.0...35
人们(天真吗?)期望将其舍入为1.0...4
,但是1.0...35
甚至在Java中可用的任何原始数据类型中都无法表示...
编辑:
我已经向Oracle提交了一份报告-希望他们能够解决或澄清这个问题。
根据Java语言规范 ,Java使用IEEE 754-1985,而您(摘自IEEE754-2008的注释)
浮点类型为float和double,它们在概念上与IEEE二进制浮点算术标准ANSI / IEEE中指定的单精度32位和双精度64位格式IEEE 754值和操作相关联标准754-1985(纽约,IEEE)。
使用DecimalFormat
setRoundingMode()
来指定舍入行为。
此行为记录在某处吗?
请参见DecimalFormat的 javadoc以及RoundingMode和IEEE 754-1985和JLS中的详细信息(此答案中的第一位陈述)
默认情况下,如所记录的那样,是Half Half Rounding模式。 HALF_EVEN
public static final RoundingMode HALF_EVEN
舍入模式将舍入到“最近的邻居”,除非两个邻居都等距,在这种情况下,将舍入到偶数邻居。 如果舍弃分数左边的数字为奇数,则表现为RoundingMode.HALF_UP; 行为与RoundingMode.HALF_DOWN相同。 请注意,这是舍入模式,当在一系列计算中重复应用时,从统计角度将累积误差降至最低。 它有时被称为“银行家四舍五入”,主要在美国使用。 此舍入模式类似于Java中用于float和double算术的舍入策略。
看来这可能是由于双舍入。
标记为“ double”的输出看起来正确地舍入为16位数字。 标记为“格式”的输出看起来像是从16位数值四舍五入(四舍五入为偶数)。
(我需要查看更多示例来验证这一点。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.