2013-02-11 2 views
3

Интересно, можно ли использовать целые числа, превышающие значение .Machine$double.xmax (~1.79e308) в R. Я думал, что, используя, например, Rmpfr или gmp библиотек в R вы можете назначать значения любого размера, вплоть до предела ОЗУ в вашей системе? Я думал, что это больше, чем .Machine$double.xmax, но это явно не так.Использование больших целых чисел с ограничениями на gmp и машине

> require(gmp) 
> as.bigz(.Machine$double.xmax) 
Big Integer ('bigz') : 
[1] 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368 
> as.bigz(1e309) 
Big Integer ('bigz') : 
[1] NA 
> 

Возможно ли кто-нибудь объяснить, почему 64-битной памяти компьютера с использованием адресации не может хранить значения больше 1.79e308? Извините - у меня нет фона для компьютерных наук, но я стараюсь учиться.

Спасибо.

+1

Вы можете найти чтение документации полезно, особенно раздел примечаний '? as.bigz'. – joran

+0

Спасибо, joran. Я пропустил последнюю строчку. Раздражающе, я не могу использовать научную нотацию сейчас! –

+2

Правда, но вы можете просто сделать 'as.bigz (10)^309'. Фактически вы можете это сделать: '"% e% "<- function (x, y) as.bigz (x) * 10^as.bigz (y); 1% e% 309' –

ответ

3

Rmpfr может выполнить преобразование строки с использованием mpfr_set_str ...

val <- mpfr("1e309") 

## 1 'mpfr' number of precision 17 bits 
## [1] 9.999997e308 

# set a precision (assume base 10)... 
est_prec <- function(e) floor(e/log10(2)) + 1 

val <- mpfr("1e309", est_prec(309)) 

## 1 'mpfr' number of precision 1027 bits 
## [1]1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 

.mpfr2bigz(val) 

## Big Integer ('bigz') : 
## [1] 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 

# extract exponent from a scientific notation string 
get_exp <- function(sci) as.numeric(gsub("^.*e",'', sci)) 

# Put it together 
sci2bigz <- function(str) { 
    .mpfr2bigz(mpfr(str, est_prec(get_exp(str)))) 
} 

val <- sci2bigz(paste0(format(Const("pi", 1027)), "e309")) 

identical(val, .mpfr2bigz(Const("pi",1027)*mpfr(10,1027)^309)) 

## [1] TRUE 

## Big Integer ('bigz') : 
## [1] 3141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587004 

Что касается почему на сохранении номера больше, чем .Machine$double.xmax, документация с плавающей точкой кодирования в IEEE спецификации, R Часто задаваемые вопросы и википедии вдаваться во все жаргоне, но я считаю, что полезно просто определить условия (с помощью ?'.Machine') ...

double.xmax (наибольший нормализованное число с плавающей точкой) =
(1 - double.neg.eps) * double.base^double.max.exp где

  1. double.neg.eps (малое положительное число с плавающей точкой х, что 1 - х = 1!) = double.base^double.neg.ulp.digits где
    • double.neg.ulp.digits = наибольшее отрицательное целое число такое, что 1 - double.base^i != 1 и
  2. double.max.exp = наименьшая положительная сила double.base, которая переполняется и
  3. double.base (радиус для представления с плавающей запятой) = 2 (для двоичных).

Думая о терминах, число конечных чисел с плавающей запятой можно отличить от другого; в IEEE спецификации говорят нам, что для ряда binary64 11 бит привыкают для показателя, поэтому мы имеем максимальный показатель степени 2^(11-1)-1=1023, но мы хотим, чтобы максимальный показатель, который перетекает так double.max.exp является 1024.

# Maximum number of representations 
# double.base^double.max.exp 
base <- mpfr(2, 2048) 
max.exp <- mpfr(1024, 2048) 

# This is where the big part of the 1.79... comes from 
base^max.exp 

## 1 'mpfr' number of precision 2048 bits 
## [1] 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216 

# Smallest definitive unit. 
# Find the largest negative integer... 
neg.ulp.digits <- -64; while((1 - 2^neg.ulp.digits) == 1) 
    neg.ulp.digits <<- neg.ulp.digits + 1 

neg.ulp.digits 

## [1] -53 

# It makes a real small number... 
neg.eps <- base^neg.ulp.digits 

neg.eps 

## 1 'mpfr' number of precision 2048 bits 
## [1] 1.11022302462515654042363166809082031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-16 

# Largest difinitive floating point number less than 1 
# times the number of representations 
xmax <- (1-neg.eps) * base^max.exp 

xmax 

## 1 'mpfr' number of precision 2048 bits 
## [1] 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368 

identical(asNumeric(xmax), .Machine$double.xmax) 

## [1] TRUE