【问题标题】:Why does this return Infinity? (Java)为什么这会返回 Infinity? (爪哇)
【发布时间】:2017-03-21 16:00:28
【问题描述】:

我试图找到 1/1 + 1/4 + 1/9 + 1/16 + 1/25 的结果 ...

这些是我写的结果Infinity

public class BaselProblem {
    public static void main(String[] args) {
        int testLimit = 100000;
        double sum = 0;
        for (int i = 1; i<testLimit; i++) 
        {
            sum = sum + 1.0/(i*i);
        }
        System.out.println(sum);
    }
}

1.0/(i*i) 更改为1/(1.0*i*i) 会得到正确的结果1.6449240667982423。为什么只有第二种形式有效,第一种无效?

还有,因为(i*i) &gt; 1,那么1.0/(i*i)应该是&lt; 1,那怎么会导致Infinity呢?

【问题讨论】:

  • i*i 将溢出int 并变为负数或零。但是1.0*i*i 是双精度的,不受同种溢出的影响。你也可以使用long
  • 奇怪的是:它是100000个数字的总和,每个数字都是
  • 认为每个数字都是&lt;1,但当i达到65536时却不是。

标签: java math types casting type-conversion


【解决方案1】:

因为您的testLimit 和您的i 被定义为int。由于您将表达式 i*i 放在括号中,因此将首先计算它,并尝试找到两个整数的倍数 - 这将很快达到溢出并重置为零。

具体来说,当i 达到 2¹⁶ 时,i*i 将是 2³²。这意味着 1 后跟 32 个二进制零,其中仅保留 32 个零,即为零。 (感谢@templatetypedef)。

因此,您将得到一个数除以零,即无穷大。

更改循环声明,使 idouble。或者乘以i*i 左手上的双精度数 (1.0)。这将导致表达式更改为 double before 乘以第二个 i

【讨论】:

  • 具体来说,当i = 2^16,那么i * i = 2^32,其中(模2^32)等于0。
  • 我没有对此进行测试,但我想如果我写了1/(i*i*1.0),那么它仍然会给出与以前相同的 Infinity 错误,因为i*i 在被类型转换为加倍之前被评估为 0?跨度>
【解决方案2】:

Java 整数的最大值为 2,147,483,647。您最终会使用 i*i 产生的整数超过该最大值。

如果您执行 1.0*i*i,您会将结果转换为可以容纳最大值 1.79769313486231570E+308 的双精度数。

i*i 的最大值将是 10,000,000,双精度可以容纳,但整数不能。

【讨论】:

    猜你喜欢
    • 2022-07-06
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    相关资源
    最近更新 更多