您的位置:首页 > 其它

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

2017-04-21 23:16 387 查看

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

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);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息