P(x)=3x6+7x5–3x4+2x3+7x2–7x–15
计算该多项式在指定的x时,P(x)的函数值。 2.问题分析
这是一个数学表达式求值问题,假设我们要求x=2时表达式的值,那么我们可以采用如下的程序代码来实现:
double x=2.0; double P;
P=3*x*x*x*x*x*x+7*x*x*x*x*x-3*x*x*x*x+2*x*x*x+7*x*x-7*x-15; System.out.printf(\
但是,如果重新换一个多项式呢?那么我们就要重新改写代码,重列一个多项式表达式来进行计算。这样显然是比较麻烦的。有没有一个通用的办法来计算多项式的值呢?答案是肯定的,我们可以采用递推的方式。首先可以将上述多项式变形为如下的等价形式: P(x)=(?((an–1x+an–2)x+an–3)x+?+a1)x+a0 通过这个表达式可以看出,只要从里往外一层一层地按照如下的方式递推,便可以计算得到整个一维多项式的值。 Rn–1=an–1
Rk=Rk+1x+ak, k=n–2,?,1,0
通过一层一层地计算后,得到的R0便是多项式P(x)的值。 (1)确定程序框架
有了前面的分析,主要分两步:第一步,如何简单地把多项式表示出来;第二步,给定x的值,把多项式的值计算出来。程序的框架如下:
public class ch2_9 {
public static void main(String[] args) {
//构造多项式 //计算多项式的值
} }
(2)构造多项式
通过前面的问题分析,我们可以知道表达式取决于x的指数及系数,这里我们假设x的指数是递增的,用一个数组存放x的系数,数组的第一项对应x的0次方,第二项对应x的1次方,??。程序的代码如下:
double a[]={-15.0,-7.0,7.0,2.0,-3.0,7.0,3.0};
(3)计算多项式的值
前面的问题分析已经找到了多项式的递推关系,我们可以通过循环的方式实现递推。程序的代码如下:
result=a[n-1];
for (i=n-2; i>=0; i--) //递推算法计算 {
result=result*x+a[i]; }
return result; //返回计算结果
(4)完整程序
现在我们就需要把刚才的程序进行组合,构成我们的完整程序:
import java.text.DecimalFormat; public class ch2_9 {
static double polynomial1D(double a[],int n,double x) {
int i;
double result; result=a[n-1];
for (i=n-2; i>=0; i--) //递推算法计算 {
result=result*x+a[i]; }
return result; //返回计算结果 }
public static void main(String[] args) {
int i;
double a[]={-15.0,-7.0,7.0,2.0,-3.0,7.0,3.0}; //表达式的系数 double[] //x值
x={-2.0,-0.5,1.0,2.0,3.7,4.0};
double result;
DecimalFormat df = new DecimalFormat(\ //数字格式
DecimalFormat df1 = new DecimalFormat(\
System.out.println(\计算P(x)=3x6+7x5-3x4+2x3+7x2-7x-15的值\ for //逐个计算结果
(i=0;
i<6;
i++)
{
result=polynomial1D(a,7,x[i]);
System.out.print(\p(x)=\ (result)+\ }
时,
System.out.print(\ } }
2.11 非线性方程求解(牛顿迭代法) 1.问题描述
非线性方程指方程中包含一个变量的幂次不是1次。例如:y=4x2–3、y=sin(x)–3x+1等等。这种方程多数不存在求根公式,从而求精确根非常困难,甚至不可能,从而寻找方程的近似根就显得特别重要。牛顿迭代法是牛顿在17世纪提出的一种求解方程f(x)=0的方法。 用牛顿迭代法求解如下的非线性方程在x0=2.0附近的方程的解:
2.问题分析
牛顿迭代法的原理:设r是f(x)=0的根,选取x0作为r初始近似值,过点(x0,f(x0))做曲线y=f(x)的切线L,L的方程为y=f(x0)+f '(x0)(x–x0),求出L与x轴交点的横坐标 x1=x0–f(x0)/f '(x0),称x1为r的一次近似值,过点(x1,f(x1))做曲线y=f(x)的切线,并求该切线与x轴的横坐标x2=x1–f(x1)/f '(x1)称x2为r的二次近似值,重复以上过程,得r的近似值序列{Xn},其中Xn1=Xn–f(Xn)/f '(Xn),称为r的n1次近似值。上式称为牛顿迭代公式。
(1)确定程序框架
上面详细分析了牛顿迭代法求解非线性方程的过程,由分析可知,除了非线性方程本身,还要用到非线性方程曲线的切线,所以还要准备好非线性方程的导数方程,然后通过牛顿迭代公式进行迭代,求出方程的近似解。程序的框架如下:
public class ch2_11 {
public static void main(String[] args) {
//构造非线性方程
//构造非线性方程的导数方程 //通过迭代公式求解
} }
(2)构造非线性方程
为简化代码,这里直接写出非线性方程。代码如下:
static
//待求解方程 {
double
func(double
x)
return x*x*x*x-3*x*x*x+1.5*x*x-4.0; }
(3)构造导数方程
为简化代码,这里直接写出非线性方程。代码如下:
static
//导数方程
double
dfunc(double
x)
{
return 4*x*x*x-9*x*x+3*x; }
(4)通过迭代公式求解
从前面的分析可知,其中Xn1=Xn–f(Xn)/f '(Xn)为牛顿迭代公式,通过它很容易写出代码,代码如下:
/**
*x代表初始值
*maxcyc代表迭代次数 *precision代表精确度
*得到结果,返回值为1,否则,返回值为0
*/
static int NewtonMethod(double[] x,int maxcyc,double precision) {
double x0,x1; int i;
x0=x[0]; //参数传递迭代初始值
i=0;
while(i { if(dfunc(x0)==0.0) //若通过初值,方法返回值为0 { System.out.print(\迭代过程中导数为0!\\n\ return 0; } x1=x0-func(x0)/dfunc(x0); //牛顿迭代计算 if(Math.abs(x1-x0) //达到预设的结束条件 { x[0]=x1; //返回结果 return 1; } else //未达到结束条件 { x0=x1; //准备下一次迭代 } i++; //迭代次数累加 } System.out.print(\迭代次数超过预设值!仍没有达到精度!\\n\ return 0; } (5)完整程序 现在我们就需要把刚才的程序进行组合,构成我们的完整程序: public class ch2_11 { static double func(double x) //待求解方程 { return x*x*x*x-3*x*x*x+1.5*x*x-4.0; } static double dfunc(double x) //导数方程 { return 4*x*x*x-9*x*x+3*x; } static int NewtonMethod(double[] x,int maxcyc,double precision) { double x0,x1; int i; x0=x[0]; //参数传递迭代初始值i=0 while(i { if(dfunc(x0)==0.0) //若通过初值,方法返回值为0 { System.out.print(\迭代过程中导数为0!\\n\