为什么Java允许在double字面量中使用任意精度?

6

我刚从Peter Lawreys的帖子中了解到这是一个有效的表达式,并且评估为true

333333333333333.33d == 333333333333333.3d

我的问题是,为什么允许存在双倍数字面量,而这些数值不能在双精度浮点数中表示,而无法表示的整数字面量却被禁止。这个决定的理由是什么。
另外,我可以实际触发双精度浮点数字面量的超出范围编译错误。
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999d

只要我们在(min,max)范围内,字面量就会被近似,但当超出该范围时,编译器似乎拒绝进行近似处理。

5
如果不允许使用0.1,你建议我们如何轻松地表示“尽可能接近0.1”的双精度数? - Jon Skeet
好观点。多显而易见啊... :P - aioobe
2个回答

9
问题在于,你输入的大多数小数都无法被IEEE浮点数精确表示。因此,如果删除所有非精确常量,则使用双精度字面量将变得非常不便。大多数情况下,“假设我们可以表示它”的行为更加有用。

这些表示并不在-MAX和MAX之间均匀分布,因此,“尽力而为”的表示对某些人来说比其他人好得多。你展示的例子恰巧很糟糕。 - Flexo

2
主要原因可能是Java无法判断何时精度不足,因为没有CPU操作码来实现这一点。
为什么没有CPU标志或类似的东西呢?因为数字的表示根本不允许这样做。例如,即使是简单的数字“0.1”也没有明确的表示。0.1会给你“00111111 10111001 10011001 10011001 10011001 10011001 10011001 10011010”(参见http://www.binaryconvert.com/result_double.html?decimal=048046049)。
该值并不是精确的0.1,而是1.00000000000000005551115123126E-1
因此,即使对于这些“简单”情况,代码也必须抛出异常。

2
可以确定一个十进制数是否可以精确表示,尽管我认为这可以在不需要CPU操作码的情况下完成。 - Flexo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接