数值计算——一维非线性方程求解

数值计算——一维非线性方程求解

1、二分法

         把函数f(x)的零点所在的区间[a,b](满足f(a)●f(b)<0)“一分为二”,得到[a,m]和[m,b]。根据“f(a)●f(m)<0”是否成立,取出零点所在的区间[a,m]或[m,b],仍记为[a,b]。所对得的区间[a,b]重复上述步骤,直到包含零点的区间[a,b]“足够小”,则[a,b]内的数可以作为方程的近似解。
数值计算——一维非线性方程求解_第1张图片
package com.kexin.lab6;

import java.text.DecimalFormat;

/**
 * 二分法求解非线性方程组
 * @author KeXin
 *
 */
public class Bisection {
	//精度
	final static double tol = 0.000001;
	/**
	 * 定义函数x^3-2x-5,返回指定x的函数值
	 * @param a
	 * @return
	 */
	public static double Function(double a){
//		double result = Math.pow(a, 2)-4*Math.sin(a);	//书上的例题测试
		double result = Math.pow(a, 3)-2*a-5;
		return result;
	}
	/**
	 * 二分法定有根区间
	 * @param a
	 * @param b
	 * @return
	 */
	public static void Bisect(double a,double b){
		DecimalFormat df  = new DecimalFormat("#.000000");
		double m;
		System.out.println("a\t\tF(a)\t\tb\t\tF(b)");
		while((b-a)>tol){
			m = a+(b-a)/2;
			if(Math.signum(Function(a))==Math.signum(Function(m))){
				a = m;
			}else{
				b = m;
			}
			System.out.println(df.format(a)+"\t"+df.format(Function(a))+"\t"+df.format((b))+"\t"+df.format(Function(b)));
		}
	}
	public static void main(String[] args) {
		double a = 1;
		double b = 3;
		Bisect(a,b);
	}

}

2、牛顿法

       在非线性方程ƒ(x)=0的零点x=x邻域内,函数 ƒ(x)连续可微且ƒ┡(x)不为零,xn(n=0,1,2,…)是x近似值,则在此邻域,用线性函数g(x) = f+f'(x-x0)代替f(x)并将g(x)的零点作为新的x近似值进行迭代求解:
        牛顿法收敛很快,而且可求复根,缺点是对重根收敛较慢,但是要求函数的一阶导数存在。
package com.kexin.lab6;

import java.text.DecimalFormat;

/**
 * 牛顿法求非线性方程组
 * 
 * @author KeXin
 *
 */
public class Newton {
	// 精度
	final static double tol = 0.000001;

	/**
	 * 定义函数x^3-2x-5,返回指定x的函数值
	 * 
	 * @param a
	 * @return
	 */
	public static double Function(double a) {
		// double result = Math.pow(a, 2)-4*Math.sin(a); //书上的例题测试
		double result = Math.pow(a, 3) - 2 * a - 5;
		return result;
	}

	/**
	 * 定义函数x^2-2即F的导数,返回指定x的函数值
	 * 
	 * @param a
	 * @return
	 */
	public static double Function1(double a) {
		// double result = 2*a-4*Math.cos(a); //书上的例题测试
		double result = 3 * Math.pow(a, 2) - 2;
		return result;
	}
	/**
	 * 牛顿法
	 * 
	 * @param a
	 * @param b
	 * @return
	 */
	public static void NewtonF(double x, int k) {
		DecimalFormat df = new DecimalFormat("#.000000");
		System.out.println("k\tx\t\tF(x)\t\tF1(x)\t\tH(x)");
		double f, f1, f2;
		while (k >= 0) {
			f = Function(x);
			f1 = Function1(x);
			f2 = -f/f1;
			System.out.println(k + "\t" + df.format(x) + "\t" + df.format(f) + "\t" + df.format(f1) + "\t" + df.format(f2));
			if ((Math.abs(f) < tol && (Math.abs(f2) / Math.abs(x)) < tol))
				break;
			x = x + f2;
			k--;
		}
	}

	public static void main(String[] args) {
		int k = 4;
		double x = 3.0;
		NewtonF(x, k);
	}

}

3、割线法

        用区间[tk-1,tk](或[tk,tk-1])上的割线近似代替目标函数的 导函数的曲线。并用割线与横轴交点的横坐标作为方程式的根的近似。
package com.kexin.lab6;

import java.text.DecimalFormat;

/**
 * 割线法求解非线性方程
 * 
 * @author KeXin
 *
 */
public class Secant {
	// 精度
	final static double tol = 0.000001;

	/**
	 * 定义函数x^3-2x-5,返回指定x的函数值
	 * 
	 * @param a
	 * @return
	 */
	public static double Function(double a) {
//		 double result = Math.pow(a, 2)-4*Math.sin(a); //书上的例题测试
		double result = Math.pow(a, 3) - 2 * a - 5;
		return result;
	}
	/**
	 * 牛顿法
	 * 
	 * @param a
	 * @param b
	 * @return
	 */
	public static void SecantF(double x0,double x, int k) {
		DecimalFormat df = new DecimalFormat("#.000000");
		System.out.println("k\tx\t\tF(x)\t\tH(x)");
		double f, f1, h = 0,temp;
		while (k >= 0) {
			f = Function(x);
			f1 = Function(x0);
			System.out.println(k + "\t" + df.format(x) + "\t" + df.format(f) + "\t"+df.format(h));
			temp = x;
			x = x - f*(x-x0)/(f-f1);
			x0 = temp;
			h = x-x0;
			k--;
		}
	}
	public static void main(String[] args) {
		SecantF(3,1,8);
	}

}

你可能感兴趣的:(数值计算)