5

考虑以下java代码:

String toParse = "1.7976931348623157E308"; //max value of a double in java        
double parsed = Double.parseDouble(toParse);
System.out.println(parsed);

因为提到的1.7976931348623157E308一切都是有意义的,并且得到了正确的输出。

现在,如果尝试解析1.7976931348623158E308(递增前的最后一位E),您仍然会在控制台中打印出最大值!
只有在尝试解析1.7976931348623159E308(最后一位数字再次增加)并且更大的一位得到Infinity.
相应的负值的行为相同。

为什么... 8E308解析为... 7E308而不是Infinity

4

1 回答 1

10

parseDouble 文档的 SE 7 版本是指 valueOf 文档,它说:

请注意,四舍五入规则也意味着溢出和下溢行为;如果 s 的确切值在幅度上足够大(大于或等于 (MAX_VALUE + ulp(MAX_VALUE)/2),则四舍五入将导致无穷大,并且如果 s 的确切值在幅度上足够小(小于大于或等于 MIN_VALUE/2),四舍五入到浮点数将导致零。

这与根据 IEEE 754 浮点运算的通常舍入到最近规则的说法一致。

您必须想象通过首先计算忽略指数限制的最接近的浮点数,然后检查指数是否适合来完成转换。Double.MAX_VALUE 是该规则下与某些严格大于它的数字最接近的数字。

要确认这是正常的舍入行为,请考虑以下程序:

    public class Test {
      public static void main(String[] args) {
        double ulp = Math.ulp(Double.MAX_VALUE);
        System.out.println(ulp);
        System.out.println(Double.MAX_VALUE);
        System.out.println(Double.MAX_VALUE+ulp/2.0000000001);
        System.out.println(Double.MAX_VALUE+ulp/2);
      }
    }

它输出:

1.9958403095347198E292
1.7976931348623157E308
1.7976931348623157E308
Infinity

向 Double.MAX_VALUE 添加甚至略小于半个 ulp 的内容也不会改变它。添加半个 ulp 会溢出到无穷大。

于 2012-11-24T03:08:35.203 回答