2012-07-28 145 views
35

当输入1e9999999999999999999999999999999到R中时,R挂起并且不会响应 - 要求终止它。为什么数字1e9999 ...(31 9s)在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挂起。他们必须修补它。

+0

爱主流理论!顺便说一句 - 这也发生在我身上。也许是记忆的东西? – 2012-07-28 11:53:40

+0

更好:'boom < - paste(c(“10 ^”,rep(9,31)),collapse =“”)'作品:P – nico 2012-07-28 11:58:27

+0

这很有趣。看起来'1e9 ...'效果不好,但'1^9 ...'效果不错。 – 2012-07-28 12:12:41

回答

24

这看起来像是解析器中的极端情况。格式在R Language DefinitionSection 10.3.1: Literal Constants中描述,并指向?NumericConstants以获得“关于当前接受的格式的最新信息”。

问题似乎是解析器如何处理指数。数字常数由NumericValue(线的main/gram.c 4361),它调用mkFloat(线的main/gram.c 4124),它调用R_atof(线的main/util.c 1584),它调用R_strtod4(线的main/util.c 1461)来处理。 (均为修订版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(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),并且该号码是数值除此之外的方式

+0

我担心这些事情对此,“怀疑这将得到R核心的任何关注” - 正在不断增长。我在过去几周发了两封邮件,没有回复。 : -/ – 2012-07-30 16:05:45

+1

在这个集合和“我会问R核心这个问题(或者提交这个补丁),但我确信我会得到彻底打击”的设置,我很难加强参与。 – 2012-07-30 20:13:32

+4

我希望*任何*溢出,不管上下文如何,都会被认为是可修补的。 – 2012-07-30 20:14:25

4

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

我宁愿在R的论坛或邮件列表上提出这个问题,这些传闻是友好的。

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

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

它可以用指数+/- 2 * 10^9来_parse_数字常量,但不能表示它们,因为双精度值被限制在大约2e-308到2e + 308(参见'?double')。 – 2012-07-30 17:56:05

+2

我不会说它正确解析它们。该表示在+ Inf和0之间保持不变,这仅取决于指数中的位数。如果正确解析,它会拒绝输入或将所有这些输入映射到+ Inf。 – 2012-07-30 18:48:16

+0

我只说它可以解析指数直到带符号的整数范围,并且一旦指数大于那个值,结果只在'0'和'Inf'之间变化,并且你在解析器中溢出指数变量:'const < - paste0( “1e”,2 ^(10:32-1); for(n in const)print(eval(parse(text = n)))'。 – 2012-07-30 18:58:50

相关问题