R语言--(7)--自定义函数

变量名 <- function(arg_1, arg_2, ...) expression

例1 求一元方程的根

编写一个用二分法求非线性方程根的函数,并求方程 x 3 − x − 1 = 0 x^3 -x -1 =0 x3x1=0 在区间 [ a , b ] [a,b ] [a,b] 内的根,精度要求 ϵ = 1 0 − 6 \epsilon=10^{-6} ϵ=106
绘制函数图像

x=seq(-5,5,0.1);x
f=x^3-x-1
plot(x,f,type="l", lwd=2,col="red",ylim=c(-2,2),main="f=x^3-x-1")

在这里插入图片描述
解题思路
取初始化区间 [ a , b ] [a,b ] [a,b], 当 f ( a ) f(a) f(a) f ( x ) f(x) f(x)异号,作二分法计算;否则停止计算(输出计算失败信息)

二分法计算过程
取中点 x = a + b 2 x=\frac{a+b}{2} x=2a+b, 则 f ( a ) f(a) f(a) f ( x ) f(x) f(x) 异号,则 b=x; 否则 a = x. 当区间长度小于指定要求时,停止计算.

fzero <- function(f,a,b,eps=1e-5){
	if (f(a)*f(b)>0)
		list(fail="finding root is fail!")
	else{
		repeat {
			if (abs(b-a)<eps) break      # abs() 取绝对值
			x <- (a+b)/2
			if (f(a)*f(x)<0)
				b <- x
			else
				a <- x
		}
		list(root=(a+b)/2, fun=f(x))
	}
}

在这里插入图片描述

f <- function(x){
	x^3 - x - 1
}

在这里插入图片描述

fzero(f,1,2,1e-6)

$root 相当于 x 的值 $fun 相当于 y 的值
在这里插入图片描述
R语言自带求一元方程根的函数 uniroot()

uniroot(f, interval, lower=min(interval),upper=max(interval), tol = .Machine$double.eps^0.25, maxiter = 1000, ...)

参数 f 是定义的函数
在这里插入图片描述

例2:计算两样本T统计量

两个分布

A <- c(79.98, 80.04, 80.02, 80.04, 80.03, 80.03, 80.04, 79.97, 80.05, 80.03, 80.02, 80.00, 80.02)
B <- c(80.02, 79.94, 79.98, 79.97,79.97, 80.03, 79.95, 79.97)

当两样本的方差相同,且未知,则T统计量的计算公式为 T = ( X ˉ − Y ˉ ) S 1 n 1 + 1 n 2 T=\frac{(\bar{X}-\bar{Y})}{S\sqrt{\frac{1}{n_1}+\frac{1}{n_2}}} T=Sn11+n21 (XˉYˉ) 其中 S 2 = ( n 1 − 1 ) S 1 2 + ( n 2 − 1 ) S 2 2 n 1 + n 2 − 2 S^2=\frac{(n_1-1)S^2_1+(n_2-1)S^2_2}{n_1+n_2-2} S2=n1+n22(n11)S12+(n21)S22
X ˉ , Y ˉ \bar{X},\bar{Y} Xˉ,Yˉ 分别是两组数据的样本均值
S 1 2 , S 2 2 S^2_1,S^2_2 S12,S22 分别是两组数据的样本方差
n 1 , n 2 n_1,n_2 n1,n2 分别为两组数据的个数

twosam <- function(y1,y2){
	n1 <- length(y1);
	n2 <- length(y2);
	yb1 <- mean(y1);
	yb2 <- mean(y2);
	s1 <- var(y1);
	s2 <- var(y2);
	s <- ((n1-1)*s1 + (n2-1)*s2)/(n1+n2-2)
	(yb1 - yb2)/sqrt(s*(1/n1 + 1/n2))
}

调用

twosam(A,B)

在这里插入图片描述

自定义二元运算 %anything%

设x,y 是两个向量,定义x与y的内积
⟨ x , y ⟩ = exp ⁡ ( − ∥ x − y ∥ 2 / 2 ) \langle x,y \rangle = \exp{(-\Vert x-y\Vert^2 /2 )} x,y=exp(xy2/2)

"%!%" <- function(x,y){
	exp(-0.5*(x-y) %*% (x-y))
}

有名参数与省略

“name=object" 给出被调用函数中的参数,则这些参数可以按照任意顺序给出

fun1 <- function(data, data.frame, graph, limit){
	...boby omitted ...
}

等价

ans <- fun1(d, df, TRUE, 20)
ans <- fun1(d, df, graph=TRUE, limit=20)
ans <- fun1(data=d, limit=20, graph=TRUE, data.frame=df)

使用 Newton 求解非线性方程组解

Newton 牛顿迭代法
方程 { x 1 2 + x 2 2 − 5 = 0 ( x 1 + 1 ) x 2 − ( 3 x 1 + 1 ) = 0 \left\{ \begin{array}{ccc} x_1^2+ x_2^2 -5=0 \\ (x_1 + 1)x_2 - (3x_1 + 1)=0 \\ \end{array} \right. {x12+x225=0(x1+1)x2(3x1+1)=0的解,取初始点 x ( 0 ) = ( 0 , 1 ) T x^{(0)} = (0,1)^T x(0)=(0,1)T, 精度要求 ϵ = 1 0 − 5 \epsilon=10^{-5} ϵ=105

解:求解非线性方程组 f ( x ) = 0 , f : R n → R n ∈ C 1 f(x)=0, f:R^n \rightarrow R^n \in C^1 f(x)=0,f:RnRnC1 的Newton法的迭代格式为
x ( k + 1 ) = x ( k ) − [ J ( x ( k ) ) ] − 1 f ( x ( k ) ) , k = 0 , 1 , … x^{(k+1)}=x^{(k)}-[J(x^{(k)})]^{-1}f(x^{(k)}), k=0,1,\dots x(k+1)=x(k)[J(x(k))]1f(x(k)),k=0,1,
其中 J ( x ) J(x) J(x) 为函数 f ( x ) f(x) f(x) 的 Jacobi 矩阵:
J ( X ) = [ ∂ f 1 ∂ x 1 ∂ f 1 ∂ x 2 … ∂ f 1 ∂ x n ∂ f 2 ∂ x 1 ∂ 2 1 ∂ x 2 … ∂ f n ∂ x n ∂ f n ∂ x 1 ∂ f n ∂ x 2 … ∂ f n ∂ x n ] J(X)= \begin{bmatrix} \frac{\partial f_1}{\partial x_1} & \frac{\partial f_1}{\partial x_2} & \dots & \frac{\partial f_1}{\partial x_n} \\ \frac{\partial f_2}{\partial x_1} & \frac{\partial 2_1}{\partial x_2} & \dots & \frac{\partial f_n}{\partial x_n} \\ \frac{\partial f_n}{\partial x_1} & \frac{\partial f_n}{\partial x_2} & \dots & \frac{\partial f_n}{\partial x_n} \end{bmatrix} J(X)=x1f1x1f2x1fnx2f1x221x2fnxnf1xnfnxnfn

Newtons <- function(fun, x, ep=1e-5, it_max=1000){
	index <- 0;
	k <- 1;
	while(k<=it_max){
		x1 <- x;
		obj <- fun(x);
		x <- x -solve(obj$J, obj$f);
		norm <- sqrt((x-x1) %*% (x-x1))
		if(norm < ep){
			index <- 1; break
		}
		k <- k + 1
	}
	obj <- fun(x);
	list(root=x, it=k, index=index, FunVal = obj$f)
}

在这里插入图片描述

funs <- function(x){
	f <- c(x[1]^2+x[2]^2-5, (x[1]+1)*x[2]-(3*x[1]+1))
	J <- matrix(c(2*x[1], 2*x[2], x[2]-3, x[1]+1), nrow=2, byrow=T);
	list(f=f,J=J);
}

在这里插入图片描述

Newtons(funs, c(0,1))

在这里插入图片描述

递归函数计算积分

使用递归函数计算数值积分 ∫ 1 5 d x x \int^5_1\frac{dx}{x} 15xdx,精度要求 ϵ = 1 0 − 6 \epsilon = 10 ^{-6} ϵ=106
解题思路
采用自动选择步长的复化梯形公式,方法为:每次将区间二等分,在子区间上采用梯形求积公式,如果计算满足精度要求或达到最大迭代次数,则停止计算;否则继续将区间对分

area <- function(f, a, b, eps=1.0e-6, lim = 10){
	fun1 <- function(f,a,b,fa,fb, a0, eps, lim, fun){
		d <- (a+b)/2;
		h <- (b-a)/4;
		fd <- f(d)
		a1 <- h * (fa + fd);
		a2 <- h * (fd + fb)
		if (abs(a0 - a1 -a2) < eps || lim == 0)
			return(a1 + a2)
		else{
			return(fun(f,a,d,fa,fb,a1,eps,lim-1,fun) + fun(f,d,b,fd,fb,a2,eps,lim-1,fun))
		}
	}
	fa <- f(a);
	fb <- f(b);
	a0 <- ((fa + fb) * (b-a))/2
	fun1(f,a,b,fa,fb,a0,eps,lim,fun1)
}

在这里插入图片描述

f <- function(x){
	1/x
}

在这里插入图片描述

quad <- area(f,1,5); quad

在这里插入图片描述

  • 8
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值