4 均匀分布随机数生成
set.seed(1024)
4.1 习题
习题1
易证。
习题2
解:
将[0,1]等分为\(k\)段,每个端点分别为\(x_i=i/k,i=0,\dots,k\),考虑左闭右开区间,如果给定点\(x\)落在\(x_i\le x<x_{i+1}\)中,有\(i/k\le x<(i+1)/k\),即\(i\le kx <i+1\),\(\lfloor kx \rfloor=i\),若\(x<0\)或\(x>1\)报错。
<- function(x, k)
runif.chisq.test
{<- rep(0,k)
y for (i in seq_along(x)) {
<- floor(k*x[[i]]) # 第j段
j if(x[[i]]==1){
<- y[[k]]+1
y[[k]] else if(j<0 | j>=k){
}stop("there is value of x out of [0,1]")
else{
}+1]] <- y[[j+1]]+1
y[[j
}
}chisq.test(y)
}
测试一下:
<- runif(1000)
x <- 10
k runif.chisq.test(x,k)
#>
#> Chi-squared test for given probabilities
#>
#> data: y
#> X-squared = 3.06, df = 9, p-value = 0.9619
通过检验。
<- rnorm(1000)
x <- x[x>=0&x<=1]
x <- 10
k runif.chisq.test(x,k)
#>
#> Chi-squared test for given probabilities
#>
#> data: y
#> X-squared = 20.047, df = 9, p-value = 0.01763
显著性水平0.05下拒绝原假设。
习题3
解:
类似地,这里对输入数据的最小值与最大值之间等分\(k\)段,每个端点分别为\(x_i=i/k,i=0,\dots,k\),考虑左闭右开区间,如果给定点\(x\)落在\(x_i\le x<x_{i+1}\)中,有\(i/k\le x<(i+1)/k\),即\(i\le kx <i+1\),\(\lfloor kx \rfloor=i\)。
# F为分布函数
<- function(x, k, F)
random.chisq.test
{library(purrr)
<- min(x)
xmin <- max(x)
xmax <- xmax-xmin
d <- floor(k*(x-xmin)/d)
j <- rep(0,k+2)
y for (i in seq_along(x)) {
if(x[[i]]==max(x)){
+1]] <- y[[k+1]]+1
y[[kelse{
}+2]] <- y[[j[[i]]+2]]+1
y[[j[[i]]
}
}<- seq(xmin,xmax,length.out = k+1) %>%
p map_dbl(F)
<- c(p[[1]],diff(p),1-p[[k+1]])
p chisq.test(y,p = p)
}
测试:
<- rnorm(1000)
x <- 10
k random.chisq.test(x,k,pnorm)
#> Warning in chisq.test(y, p = p): Chi-squared approximation may be incorrect
#>
#> Chi-squared test for given probabilities
#>
#> data: y
#> X-squared = 8.422, df = 11, p-value = 0.6751
<- runif(1000)
x <- 10
k random.chisq.test(x,k,pnorm)
#>
#> Chi-squared test for given probabilities
#>
#> data: y
#> X-squared = 2044.9, df = 11, p-value < 2.2e-16
通过测试。
习题4
解:
这个应该是下一节的内容,不过无所谓啦。先得到它的分布函数为 \[ F(x) = \frac12x+\frac12x^2,\quad0\le x\le1 \]
1、逆变换法:
先求\(F^{-1}\)为: \[ F^{-1}(u) = -\frac12+\sqrt{2u+\frac14} \] 从而定义函数:
<- function(n)
rng.x1
{-0.5+sqrt(2*runif(n)+0.25)
}
测试:
<- 1000
n <- rng.x1(n)
x hist(x,freq = FALSE)
<- seq(0,1,0.01)
y <- 0.5+y
z lines(y,z,col="red")
基本吻合。
2、舍选法
就是拒绝采样啦,取提议分布为均匀分布\(U[0,1]\),则\(c=1.5\).
<- function(n)
rng.x2
{<- runif(n)
x <- runif(n,0,1.5)
y <- x[y<=0.5+x]
s list(samples = s, eff = length(s)/n)
}
测试:
<- 1000
n <- rng.x2(n)
x hist(x$samples,freq = FALSE)
<- seq(0,1,0.01)
y <- 0.5+y
z lines(y,z,col="red")
基本吻合。看一下效率:
$eff
x#> [1] 0.669
理论上的效率为\(2/3\)。
3、复合法
将梯形面积分解为一个矩形跟一个三角形,两者面积都是0.5。
<- function(n)
rng.x3
{<- runif(n)
i <- runif(n)
x # 小于等于0.5保持值,大于0.5开平方
>0.5] <- sqrt(x[i>0.5])
x[i
x }
测试:
<- 1000
n <- rng.x3(n)
x hist(x,freq = FALSE)
<- seq(0,1,0.01)
y <- 0.5+y
z lines(y,z,col="red")
比较算法的效率?除了舍选法会拒绝点之外,其余两者算法都是全部接受点的。看一下函数的运行时间吧,虽然这个比较粗糙,因为跟算法编码的设计有关,不一定是算法本身的问题:
<- 10000000
n .1 <- proc.time()
t1<- rng.x1(n)
x .2 <- proc.time()
t1<- t1.2-t1.1
t1 .1 <- proc.time()
t2<- rng.x2(n)
x .2 <- proc.time()
t2<- t2.2-t2.1
t2 .1 <- proc.time()
t3<- rng.x3(n)
x .2 <- proc.time()
t3<- t3.2-t3.1
t3 <- data.frame(`逆变换法`=t1[3][[1]],`舍选法`=t2[3][[1]],`复合法`=t3[3][[1]])
df ::kable(df) knitr
逆变换法 | 舍选法 | 复合法 |
---|---|---|
0.52 | 1.06 | 1.1 |
总的来说,逆变换法要更好点,舍选法要稍差点。