我正在尝试将牛顿公式应用于长度为n = 500的反向采样方法。 (u统一随机数,Fphi_x我们根据分布,fphi_x是我们的密度)。 然后牛顿公式:找到x,使得Fphi_x(x)-u = 0
`u=runif(500)
xnewton=rep(1e-30,500)
fphi_x=function(x){return(0.307/(x^{5/12}*(x+1)))}
Fphi_x=function(u){k=integrate(fphi_x,0,u)$value
return(k)}
for(i in 1:500)
{
while(abs(Fphi_x(xnewton[i])-u[i])>0.0000001){
xnewton[i]=xnewton[i]-(Fphi_x(xnewton[i])-u[i])/fphi_x(xnewton[i])
}
}`
代码正确。但是我得到了错误代码:
Error in integrate(fphi_x, 0, u) : the integral is probably divergent.
我发现了:
Fphi_x(1e15)=1.197390096030634e-05
但如果我有小数位;例如
Fphi_x(10000000000.000000)
我收到错误消息。
根据我的发行版,我会默默地获得高数字,例如小数位数,例如431232.132131。怎么解决?
最好的问候
答案 0 :(得分:0)
这个问题似乎与你的被积函数在其下界无限的事实有关;
> fphi_x(0)
[1] Inf
显然integrate
可以处理较小的上限而不是较大的上限。我尝试了几种方法。似乎有用的一个是改变积分
y = 1/x
保持被积函数有限,但明确地使上界无限。然后,您可以使用quadinf
包中的积分函数pracma
,它允许积分上的无限边界。
为了比较两个集成例程的结果,使用了set.seed(100)
来修复为u
返回的随机值。使用u
的这些值,integrate
函数将处理u
的前126个值,而quadinf
将计算所有500个值。每个的前126个值都相同
两者的代码如下:
set.seed(100)
u=runif(500)
xnewton=rep(1e-30,500)
fphi_x=function(x){return(0.307/(x^{5/12}*(x+1)))}
Fphi_x=function(u){ k=integrate(fphi_x,0,u)$value
return(k)}
for(i in 1:126)
{
while(abs(Fphi_x(xnewton[i])-u[i])>0.0000001){
xnewton[i]=xnewton[i]-(Fphi_x(xnewton[i])-u[i])/fphi_x(xnewton[i])
}
}
xnewton_x <- xnewton
#
# using change of variable y = 1/x and quadinf function
#
library(pracma)
xnewton=rep(1e-30,500)
fphi_y <- function(y) .307*y^(5/12-1)/(1+y)
Fphi_y <- function(u) quadinf(fphi_y, 1/u, Inf)$Q
for(i in 1:500)
{
while(abs(Fphi_y(xnewton[i])-u[i])>0.0000001){
xnewton[i] <- xnewton[i]- (Fphi_y(xnewton[i]) - u[i])/fphi_x(xnewton[i])
}
}
xnewton_y <- xnewton
quadinf
似乎需要比integrate
更长的时间来运行,但至少似乎会在integrate
失败的情况下返回结果。