为什么数字1e9999 ...(31 9s)导致R出现问题?

时间:2012-07-28 11:48:41

标签: r

1e9999999999999999999999999999999输入R时,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-09-15,这不再导致R挂起。他们必须修补它。

3 个答案:

答案 0 :(得分:24)

这看起来像解析器中的极端情况。 Section 10.3.1: Literal ConstantsR Language Definition中描述了XeY格式,并指向?NumericConstants以获取有关当前接受格式的最新信息。

问题似乎是解析器处理指数的方式。数字常量由NumericValuemain/gram.c的第4361行)处理,调用mkFloatmain/gram.c的第4124行),调用R_atof(第1584行) of main/util.c),调用R_strtod4main/util.c的第1461行)。 (全部修订于60052年。)

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

例如,下面的代码生成指数值&lt; 308左右,Inf表示指数&gt; 308。

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

您可以看到指数的未定义行为&gt; 2 ^ 31(R挂起指数= 2 ^ 31):

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

我怀疑这会引起R-core的注意,因为R只能存储大约2e-308到2e + 308之间的数值(见?double),这个数字是方式除此之外。

答案 1 :(得分: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,但它不能代表它们。之后,由于溢出,显然存在未定义的行为。

答案 2 :(得分:4)

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

我宁愿在专门针对 R 的论坛或邮件列表上提出这个问题,据说这些问题很友好。

或者,由于 R 是免费软件,您可以调查其源代码。