为什么数字1e9999 …(31 9s)在R中导致问题?

当input1e9999999999999999999999999999999到R时,R挂起并不会响应 – 要求终止。

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

这里有一些代码可以更容易地生成数字:

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

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

奇怪的是,如果你尝试1e9999999999999999999999999999998或者1e10000000000000000000000000000000 (加上或减去1),你分别得到Inf0 。 这个数字显然是某种边界,但是在这个什么和为什么呢?

我认为这可能是:

  • 一个浮点问题,但我认为他们最多在1.7977e308,早在这个数字之前。
  • 一个32位整数的问题,但2 ^ 32是4294967296,远远小于所讨论的数量。
  • 真奇怪。 这是我的主导理论。

编辑:截至2015-09-15最迟,这更长的时间导致R挂起。 他们必须修补它。

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

问题似乎是parsing器如何处理指数。 数值常量由调用R_atofmain/util.c 1584行)的R_atofmain/gram.c mkFloat第4124行)的NumericValuemain/gram.c NumericValue第4361行)来处理,它调用R_strtod4 main/util.c第1461行)。 (所有修订60052)。

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

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

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

你可以看到exponents> 2 ^ 31的未定义行为(R挂起一个指数= 2 ^ 31):

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

我怀疑这会从R核心得到任何的关注,因为R只能存储大约2e-308到2e + 308之间的数值(参见?double ),这个数字远远超过了这个数字。

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

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

我们走了,最后是合理的。 根据这一结果和下面的Joshua Ulrich的评论,R似乎支持代表数字高达约2e308,parsing指数高达+ 2 * 10 ^ 9的数字,但它不能代表它们。 之后,由于溢出,显然存在未定义的行为。

R有时可能使用bignums 。 也许1e9999999999999999999999999999999是一些门槛,或者也许parsing例程有一个有限的读取指数的缓冲区。 您的观察将与指数的32位字符(以空字符结尾)缓冲​​区一致。

我宁愿在R的论坛或邮件列表上提出这个问题。

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