【问题标题】:Using Double.POSITIVE_INFINITY in for loop (Java)在 for 循环中使用 Double.POSITIVE_INFINITY (Java)
【发布时间】:2015-11-04 18:46:08
【问题描述】:

以下代码将如何表现,尤其是当双计数器达到其极限 ((2-2^-52)·2^1023) 时?

for (double i = 0; i < Double.POSITIVE_INFINITY; i++){
    //do something
}

此代码会按预期运行(永远循环)还是在某些时候失败?为什么?

谢谢。

【问题讨论】:

  • 我认为不能保证它会达到那个值。谁能说 i 在达到该值之前不会下溢,因为双重算术的行为方式?
  • 为什么不试试呢?
  • @Makoto 这基本上就是我要问的。这里唯一有趣的情况是边缘情况。
  • 我不确定我是否认为这本身很“有趣”...如果您想要无限循环,是否有充分的理由避免while(true)
  • @Makoto 好吧,在我目前的情况下,它比较的变量可以是正常值,也可以是无穷大,以防您想永远运行循环。我认为这是实现这一目标的最简单最方便的方法。

标签: java for-loop infinity


【解决方案1】:

在某些时候,i++ 将停止产生任何影响,因为对于非常大的 i 值,连续的 double 值相距甚远。

因此它是一个无限循环。

要证明有 double 值,i == i + 1 试试这个:

for (double i = 1;; i *= 2){
    if (i == i + 1) {
        System.out.println(i); 
        break;
    }
}

打印出来

9.007199254740992E15

【讨论】:

  • 这很有趣,不知道。增量是否永远停止生效,或者只需要很长时间才能看到变化?这个循环还会导致计数器溢出吗?
  • @Samir 它没有任何效果。这不是“秘密”在某处保留增长;一旦i 变得足够大,就没有任何变化。一旦i 达到该值,它完全停止更改
  • @Samir 浮点值没有无限分辨率en.wikipedia.org/wiki/Unit_in_the_last_place 是您需要走的最小“步”。此时大于 1
  • @LouisWasserman 好吧,现在更有意义了,谢谢。如果计数器是整数怎么办?它会溢出并仍然无限循环吗?
  • @Samir 整数类型 intcharbyteshortlong 全部溢出。如果您添加一个,例如Integer.MAX_VALUE 你会得到Integer.MIN_VALUE。整数类型的值没有i == i + 1
【解决方案2】:

这段代码永远不会退出循环。

这样做的原因是,将1 添加到足够大的double 数字不会改变其值:

double a = 1.7976931348623155E308;
double old = a;
a++;
System.out.println(a);      // prints 1.7976931348623155E308
System.out.println(old);    // prints 1.7976931348623155E308
System.out.println(a==old); // prints "true"

Demo.

实际上,当double 的值足够接近正无穷大时,您需要添加一个远高于 10200 的数字,以使您的大双变化值成为@987654326 @。

原因是double 表示大数的方式。它使用短 尾数 来表示值的最高有效数字,并使用指数来指示小数点应该放在哪里。在非常大的数字的情况下,指数本质上表示在尾数的二进制表示之后需要添加多少个零。

为了使您的double 数字通过加法改变值,您需要添加一个至少与尾数的最低有效位一样大的数字。一旦二进制指数超过 48,为使结果不同而需要添加的最小数字变为 2,这意味着 ++ 将不再更改该值。

【讨论】:

  • 完全0效果吗?位或内存没有变化?还是大量使用后会有影响?还有“足够大”到底是什么意思?
  • @Samir 大数加一无效。一旦浮点单元发现被相加的两个数字的指数将它们的尾数置于不相交的范围内,该单元就会停止并返回较大数字的值。
猜你喜欢
  • 2013-09-18
  • 2019-03-05
  • 1970-01-01
  • 2015-03-21
  • 2018-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多