R中的大数乘法

时间:2016-01-26 09:23:02

标签: r

我想知道如何在R中计算大值乘法。 R返回Inf!

例如:

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

让我更多地澄清问题: 考虑以下代码和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))

}

并且函数返回:

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

如上所示,outFunc返回Inf + NaNi,其n值为129和121。 我逐个检查了代码部分,发现这些n值的(w lam)^ k poch(r,k)的返回结果是Inf。我还用Mathematica中的等效代码检查我的代码,一切正常:

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}

现在请让我知道如何解决这个问题,就像在Mathematica中一样简单。问候。

3 个答案:

答案 0 :(得分:6)

您在基础R中可用的一个选项(不需要特殊的库)是将两个数字转换为公共基数,然后将指数一起添加以获得最终结果:

> 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

10^x * 10^y = 10^(x+y)起,您的最终答案为10^493.1489

请注意,此解决方案不允许实际存储R通常视为INF的数字。因此,在此示例中,您仍然无法计算10^493,但您可以梳理出该产品的内容。

答案 1 :(得分:4)

> library(gmp)
> x<- pow.bigz(6.350218,277)
> y<- pow.bigz(2.218789,215)
> x*y

Big Integer ('bigz') :
[1] 18592826814872791919942226542714580401488894909642693257011204682802122918146288728149155739011270579948954646130492024596687919148494136290260248656581476275790189359808616520170359345612068099238508437236172770752199936303947098513476300142414338199993261924467166943683593371648

答案 2 :(得分:4)

首先,我建议使用两个有用的读物​​:logarithmshow floating values are handled by a computer。这些是相关的,因为有了一些“技巧”,你可以处理比你想象的更大的价值。例如,您对poch函数的定义很糟糕。这是因为分数可以简化很多,但是计算机会首先评估分子,如果它溢出,结果将是无用的。这就是Rgamma lgamma函数旁边提供的原因:它只计算gamma的对数,并且可以处理更大的值。因此,我们计算函数中每个因子的log,然后我们使用exp来恢复预期值。试试这个:

#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