Подтвердить что ты не робот

Почему число 1e9999... (31 9s) вызывает проблемы в R?

При вводе 1e9999999999999999999999999999999 в R, R зависает и не будет отвечать - требуя его завершения.

Кажется, что это происходит на трех разных компьютерах, операционных системах (Windows 7 и Ubuntu). Это происходит в RStudio, RGui и RScript.

Здесь некоторый код для генерации номера проще:

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

Теперь ясно, что это не практическая проблема. Мне не нужно использовать цифры такого масштаба. Это просто вопрос любопытства.

Любопытно, что если вы попробуете 1e9999999999999999999999999999998 или 1e10000000000000000000000000000000 (добавьте или вычтите один из мощности), вы получите Inf и 0 соответственно. Это число, очевидно, является какой-то границей, но между чем и почему здесь?

Я считал, что это может быть:

  • Проблема с плавающей запятой, но я думаю, что они максимальны в 1.7977e308, задолго до числа, о котором идет речь.
  • Проблема с 32-битными целыми числами, но 2 ^ 32 - 4294967296, намного меньше, чем указанное число.
  • Действительно странно. Это моя доминирующая теория.

РЕДАКТИРОВАТЬ: По состоянию на 2015-09-15 это больше не приводит к зависанию R. Они, должно быть, исправили его.

4b9b3361

Ответ 1

Это выглядит как крайний случай в синтаксическом анализаторе. Формат XeY описан в в разделе 10.3.1: Literal Constants Определение языка 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.)

Строка 1464 из main/utils.c показывает expn, объявленную как int, и она будет переполняться в строке 1551, если экспонента слишком велика. Подписанное целочисленное переполнение вызывает поведение undefined.

Например, приведенный ниже код создает значения для экспонентов < 308 или около того и Inf для экспонентов > 308.

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

Вы можете увидеть поведение undefined для экспонентов > 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), и это число выходит за рамки этого.

Ответ 2

Это интересно, но я думаю, что у R есть системные проблемы с числами синтаксического разбора с очень большими показателями:

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

Там мы идем, наконец, что-то разумное. В соответствии с этим результатом и комментарием Джошуа Ульриха ниже, R, похоже, поддерживает отображение чисел примерно до 2e308 и разбор чисел с показателями до примерно + 2 * 10 ^ 9, но они не могут их представлять. После этого существует поведение undefined, по-видимому, из-за переполнения.

Ответ 3

R может иногда использоваться bignums. Возможно, 1e9999999999999999999999999999999 - это некоторый порог, или, возможно, подпрограммы разбора имеют ограниченный буфер для чтения экспоненты. Ваше наблюдение будет согласуется с 32 char (нулевым) буфером для экспоненты.

Я скорее спрошу этот вопрос на форумах или список рассылки, специфичный для R, которые, по слухам, дружат.

В качестве альтернативы, поскольку R является свободным программным обеспечением, вы можете исследовать его исходный код.