将1e9999999999999999999999999999999
输入R时,R挂起并且不会响应 - 要求终止。
它似乎发生在3种不同的计算机上,操作系统(Windows 7和Ubuntu)。它发生在RStudio,RGui和RScript中。
以下是一些可以更轻松地生成数字的代码:
boom <- paste(c("1e", rep(9, 31)), collapse="")
eval(parse(text=boom))
现在显然这不是一个实际问题。我没有必要使用这么大的数字。这只是好奇心的问题。
奇怪的是,如果您尝试1e9999999999999999999999999999998
或1e10000000000000000000000000000000
(从权力中添加或减去一个),则分别获得Inf
和0
。这个数字显然是某种边界,但在这里和为什么在这里之间?
我认为可能是:
编辑:最迟在2015-09-15,这不再导致R挂起。他们必须修补它。
答案 0 :(得分:24)
这看起来像解析器中的极端情况。 Section 10.3.1: Literal Constants的R Language Definition中描述了XeY
格式,并指向?NumericConstants
以获取有关当前接受格式的最新信息。
问题似乎是解析器处理指数的方式。数字常量由NumericValue
(main/gram.c
的第4361行)处理,调用mkFloat
(main/gram.c
的第4124行),调用R_atof
(第1584行) of main/util.c
),调用R_strtod4
(main/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 是免费软件,您可以调查其源代码。