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

来源:互联网 发布:手机看淘宝实名认证了 编辑:程序博客网 时间:2024/06/04 18:41

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

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]内的数可以作为方程的近似解。

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);}}
0 0
原创粉丝点击