Quiero saber cómo puedo calcular la multiplicación de valores grandes en R. ¡R devuelve Inf!

Por ejemplo:

6.350218e+277*2.218789e+215 
[1] Inf

Permítanme aclarar más el problema: considere el siguiente código y los resultados de la función outFunc:

library(hypergeo)
poch <-function(a,b) gamma(a+b)/gamma(a)
n<-c(37 , 41 , 4 , 9 , 12 , 13 , 2 , 5 , 23 , 73 , 129 , 22 , 121 )
v<-c(90.2, 199.3, 61, 38, 176.3, 293.6, 318.6, 328.7, 328.1, 313.3, 142.4, 92.9, 95.5)
DF<-data.frame(n,v)


outFunc<-function(k,w,r,lam,a,b) {
  ((((w*lam)^k) * poch(r,k) * poch(a,b) ) * hypergeo(r+k,a+k,a+b+k,-(w*lam)) )/(poch(a+k,b)*factorial(k))

}

Y la función devuelve:

outFunc(DF$n,DF$v,0.2, 1, 3, 1)
 [1] 0.002911330+  0i 0.003047594+  0i 0.029886646+  0i 0.013560599+  0i 0.010160073+  0i
 [6] 0.008928524+  0i 0.040165795+  0i 0.019402318+  0i 0.005336008+  0i 0.001689114+  0i
[11]         Inf+NaNi 0.005577985+  0i         Inf+NaNi

Como se puede ver arriba, outFunc devuelve Inf + NaNi para n valores de 129 y 121. Revisé las secciones del código parte por parte y descubrí que los resultados devueltos de (w lam) ^ k poch (r, k) para estos n valores son Inf. También verifico mi código con código equivalente en Mathematica que todo está bien:

in:  out[indata[[All, 1]], indata[[All, 2]], 0.2, 1, 3, 1]

out: {0.00291133, 0.00304759, 0.0298866, 0.0135606, 0.0101601, 0.00892852, \
      0.0401658, 0.0194023, 0.00533601, 0.00168911, 0.000506457, \
      0.00557798, 0.000365445}

Ahora, hágame saber cómo podemos resolver este problema tan simple como en Mathematica. Saludos.

r
1
Mahdi Hadi 26 ene. 2016 a las 12:23

3 respuestas

La mejor respuesta

Primero, recomendaría dos lecturas útiles: logaritmos y cómo los valores flotantes son manejados por una computadora. Estos son pertinentes porque con algunos "trucos" puedes manejar valores mucho más grandes de lo que crees. Por ejemplo, su definición de la función poch es terrible. Esto porque la fracción se puede simplificar mucho, pero una computadora evaluará primero el numerador y si se desborda, el resultado será inútil. Es por eso que R proporciona al lado de gamma la función lgamma: simplemente calcula el logaritmo de gamma y puede manejar valores mucho más grandes. Entonces, calculamos el log de cada factor en su función y luego usamos exp para restaurar los valores previstos. Prueba esto:

#redefine poch properly
poch<-function(a,b) lgamma(a+b) - lgamma(a)
#redefine outFunc
outFunc<-function(k,w,r,lam,a,b) {
   exp((k*(log(w)+log(lam))+ poch(r,k) + poch(a,b) ) +  
   log(hypergeo(r+k,a+k,a+b+k,-(w*lam)))- poch(a+k,b)-lgamma(k+1))
}
#Now we go
outFunc(DF$n,DF$v,0.2, 1, 3, 1)
#[1] 0.0029113299+0i 0.0030475939+0i 0.0298866458+0i 0.0135605995+0i
#[5] 0.0101600732+0i 0.0089285243+0i 0.0401657947+0i 0.0194023182+0i
#[9] 0.0053360084+0i 0.0016891144+0i 0.0005064566+0i 0.0055779850+0i
#[13] 0.0003654449+0i
4
nicola 26 ene. 2016 a las 11:56
> library(gmp)
> x<- pow.bigz(6.350218,277)
> y<- pow.bigz(2.218789,215)
> x*y

Big Integer ('bigz') :
[1] 18592826814872791919942226542714580401488894909642693257011204682802122918146288728149155739011270579948954646130492024596687919148494136290260248656581476275790189359808616520170359345612068099238508437236172770752199936303947098513476300142414338199993261924467166943683593371648
4
George Dontas 26 ene. 2016 a las 09:56

Una opción que tiene disponible en la base R, que no requiere una biblioteca especial, es convertir los dos números en una base común y luego sumar los exponentes para obtener el resultado final:

> x <- log(6.350218e+277, 10)
> x
[1] 277.8028
> y <- log(2.218789e+215, 10)
> y
[1] 215.3461
> x + y
[1] 493.1489

Desde 10^x * 10^y = 10^(x+y), su respuesta final es 10^493.1489

Tenga en cuenta que esta solución no permite almacenar números que R normalmente trataría como INF. Por lo tanto, en este ejemplo, todavía no puede calcular 10^493, pero puede determinar cuál sería el producto.

6
Tim Biegeleisen 26 ene. 2016 a las 09:41