1 误差
library(purrr)
1.1 习题
习题2
设某正数\(a\)四舍五入后保留了\(p\)位有效数字,表示成\(a^* = (0.a_1a_2\cdots a_p)_{10}\times10^m(a_1\ne0)\)。 估计其绝对误差和相对误差的范围, 并分析误差与有效数字位数\(p\)的关系。
解:
容易知道,\(m\ge p\)。先通过一个例子直观理解一下,不妨取\(a=12546\),当取\(p=3\),有\(a^*=0.125\times 10^5=12500\),当取\(p=4\),有\(a^*=0.1255\times 10^5=12550\)。
所以可以得到,\(m\)实际上是正数\(a\)的位数,而\(p\)则是要保留的有效数字的位数。
其绝对误差: \[ \Delta = a-a^*\le 0.5\times10^{m-p} \]
利用\(a\ge10^m\),其相对误差: \[ \delta = \frac{\Delta}{a} \le\frac{0.5\times10^{m-p}}{10^m}=0.5\times10^{-p} \]
习题3
解:
先定义通项:
<- function(n)
myfun
{-1)^(n+1)/n
(
}<- 10^6 n
<- 0
S for (i in 1:n) {
<- S+myfun(i)
S
}abs(S-log(2))
#> [1] 5e-07
<- 0
S for (i in 1:n) {
<- S+myfun(n+1-i)
S
}abs(S-log(2))
#> [1] 5e-07
<- 0
S <- vector("double",n/2)
l for (i in 1:(n/2)) {
<- myfun(2*i-1)+myfun(2*i)
l[[i]]
}for (i in l) {
<- S+i
S
}abs(S-log(2))
#> [1] 5e-07
<- vector("double",n/2)
l for (i in 1:(n/2)) {
<- 1/(2*n*2*(n-1))
l[[i]]
}for (i in l) {
<- S+i
S
}abs(S-log(2))
#> [1] 3.75e-07
第4种方法精度更高。
习题4
解:
<- 1:4
x <- function(x, k=10)
myfun1
{<- 1
S for (i in 1:k) {
<- (-x)^i/factorial(i)
m <- S+m
S
}
S
}<- function(x, k=10)
myfun2
{<- 1
S for (i in 1:k) {
<- x^i/factorial(i)
m <- S+m
S
}1/S
}<- map_dbl(x,myfun1)
s1 <- map_dbl(x,myfun2)
s2 <- exp(-x)
s <- data.frame(x,s1=abs(s1-s),s2=abs(s2-s))
df ::kable(df) knitr
x | s1 | s2 |
---|---|---|
1 | 0.000 | 0 |
2 | 0.000 | 0 |
3 | 0.004 | 0 |
4 | 0.078 | 0 |
方法1的误差太大了,不妨增大\(k\)值:
<- map_dbl(x,myfun1,k=100)
s1 <- map_dbl(x,myfun2)
s2 <- exp(-x)
s <- data.frame(x,s1=abs(s1-s),s2=abs(s2-s))
df ::kable(df) knitr
x | s1 | s2 |
---|---|---|
1 | 0 | 0 |
2 | 0 | 0 |
3 | 0 | 0 |
4 | 0 | 0 |
误差瞬间下去,说明方法1的收敛比较慢。以\(x=4\)为例,探究两个方法的收敛速度:
<- 4
x <- 1:50
k <- map_dbl(k,myfun1,x=x)
s1 <- map_dbl(k,myfun2,x=x)
s2 <- exp(-x)
s <- par(no.readonly = TRUE)
opar plot(k,abs(s1-s),"l",ylab="")
lines(k,abs(s2-s),lty=2,col="red")
title(ylab="绝对误差")
legend("topright",c("公式(1)","公式(2)"),lty=c(1,2),col=c("black","red"))
par(opar)
可以看到公式(1)的收敛速度一开始是很慢的。
习题5
解:
载入数据:
<- c(249, 254, 243, 268, 253, 269, 287, 241, 273, 306303, 280, 260, 256, 278, 344, 304, 283, 310)
x <- length(x) n
公式1:
<- 0
s1 for (i in x) {
<- signif(s1+signif(i^2,digits = 6),digits = 6)
s1
}<- signif(s1-n*mean(x),digits = 6)
s1 <- signif(s1/(n-1),digits = 6) s1
公式2:
<- 0
s2 <- mean(x)
m for (i in x) {
<- signif(s2+signif((i-m)^2,digits = 6),digits = 6)
s2
}<- signif(s2/(n-1),digits = 6) s2
比较:
<- data.frame(`函数直接计算`=var(x),`公式1`=s1,`公式2`=s2)
df ::kable(df) knitr
函数直接计算 | 公式1 | 公式2 |
---|---|---|
5.2e+09 | 5.52e+09 | 5.2e+09 |
公式2比公式1更精确,公式1先计算平方求和,值太大,保留6位有效数字之后损失较多。
习题6
解: