37

当进入1e9999999999999999999999999999999R 时,R 挂起并且不会响应 - 要求它被终止。

它似乎发生在 3 台不同的计算机、操作系统(Windows 7 和 Ubuntu)上。它发生在 RStudio、RGui 和 RScript 中。

这是一些更容易生成数字的代码:

boom <- paste(c("1e", rep(9, 31)), collapse="")
eval(parse(text=boom))

现在显然这不是一个实际问题。我不需要使用这种数量级的数字。这只是一个好奇的问题。

奇怪的是,如果你尝试1e99999999999999999999999999999981e10000000000000000000000000000000(从幂中加或减一),你会分别得到Inf0。这个数字显然是某种界限,但在什么和为什么之间呢?

我认为它可能是:

  • 一个浮点问题,但我认为它们的最大值为 1.7977e308,远早于所讨论的数字。
  • 32 位整数的问题,但 2^32 是 4294967296,比所讨论的数字小得多。
  • 真的很奇怪。这是我的主导理论。

编辑:最迟在 2015 年 9 月 15 日,这不再导致 R 挂起。他们一定已经修补过了。

4

3 回答 3

24

这看起来像是解析器中的一个极端情况。该XeY格式在第 10.3.1 节:R 语言定义的文字常量中进行了描述,并指向?NumericConstants“当前接受格式的最新信息”。

问题似乎是解析器如何处理指数。数字常量由NumericValue(第 4361 行main/gram.c)处理,它调用mkFloat(第 4124 行main/gram.c),它调用R_atof(第 1584 行main/util.c),它调用R_strtod4(第 1461 行main/util.c)。(所有内容截至修订版 60052。)

main/utils.c显示的第 1464 行expn声明为int,如果指数太大,它将在第 1551 行溢出。有符号整数溢出会导致未定义的行为。

例如,下面的代码生成指数 < 308 左右和Inf指数 > 308 的值。

const <- paste0("1e",2^(1:31)-2)
for(n in const) print(eval(parse(text=n)))

您可以看到指数 > 2^31 的未定义行为(对于指数 = 2^31,R 挂起):

const <- paste0("1e",2^(31:61)+1)
for(n in const) print(eval(parse(text=n)))

我怀疑这会引起 R-core 的任何关注,因为 R 只能存储大约 2e-308 到 2e+308 之间的数值(请参阅 参考资料?double),而这个数字不止于此。

于 2012-07-30T16:02:40.387 回答
7

这很有趣,但我认为 R 在解析具有非常大指数的数字时存在系统性问题:

> 1e10000000000000000000000000000000
[1] 0
> 1e1000000000000000000000000000000
[1] Inf
> 1e100000000000000000000
[1] Inf
> 1e10000000000000000000
[1] 0
> 1e1000
[1] Inf
> 1e100
[1] 1e+100

我们走了,终于有一些合理的东西了。根据此输出和下面 Joshua Ulrich 的评论,R 似乎支持表示高达约 2e308 的数字并解析指数高达约 +2*10^9 的数字,但它不能表示它们。之后,显然由于溢出而出现未定义的行为。

于 2012-07-28T12:28:01.103 回答
4

R有时可能会使用bignums。可能1e9999999999999999999999999999999是某个阈值,或者解析例程用于读取指数的缓冲区有限。您的观察结果与指数的 32 个字符(以空字符结尾)缓冲​​区一致。

我宁愿在论坛或特定于R的邮件列表上问这个问题,据传它们很友好。

或者,由于R是免费软件,您可以研究它的源代码。

于 2012-07-28T11:53:55.623 回答