算法:
要计算
,相当于求方程:
的正实根。解决这个问题,我们可以使用牛顿迭代公式。
对于一般的线性方程
,用牛顿迭代法求解的方法是:给定一个初值
,用下面的迭代公式:
,
得到一个迭代序列,当
(给定的精度)时,我们便认为
为方程
的根,并停止迭代。
牛顿迭代法有很明显的几何意义(参见右图5-12),当我们选定
以后,过
作
的切线,其切线方程为:
求此切线方程与x轴的交点,即得:
正因为牛顿法有这一明显得几何意义,所以也叫切线法。
本题中,因为
,
,故牛顿迭代公式为:
在区间(0, ∞)内
单调增大,
,因此,对于任取的
都收敛于s。
程序:
根据上面的算法,我们可以编出计算一个正数的、n次方的、正实根的函数NewtonRoot,也编写一个main函数,就得到一个完整的程序如下:
|
|
例5-29 |
|
#include #include #include const double SMALLFRACTION = 1.0E-8;
double NewtRoot(double x, int n) { double x0, x1, f0, f1; assert(x > 0.0); x0 = x / 2.0;x1 =x; while(fabs(x1-x0) > SMALLFRACTION*x1) { cout << r << endl; x0 = x1; f0 = pow(x0, n) - x; f1 = n*pow(x0, n-1) - x0; x1 = x0 - f0/f1; } return x1; }
void main() { double x; int n; cout << "Enter number : "; cin >> x; cout << "\nEnter exponent : "; cin >> n; cout << "Number was : " << x << ", root is " << NewtRoot (x, n) << endl; } |
|
在上面的程序中,我们定义了一个double型全局常量SMALLFRACTION,它是给定的计算精度。也就是说,迭代出的近似解必须满足该精度要求(10-8)。
NewtRoot函数有两个形参x和n,分别是待求方根的正实数及方根次数。定义了4个double型变量:x1、x0、f0和f1,分别表示:当前迭代值、前一次迭代值、前一次迭代值的函数值和前一次迭代值的函数的一阶导数值。x0的初值取形参x,x1的初始值取形参x的一半。
NewtRoot函数中用到了几个C++库函数:assert、fabs和pow。assert函数在assert.h中定义,其功能是:若形参表达式为假,则打印诊断信息,并停止应用程序的运行。fabs和pow在math.h中定义,分别是求一个double型数的绝对值与乘方。
在main函数中,分别输入待求方根的正实数及方根次数,然后调用NewtRoot,并输出计算结果。
假定编译、运行该程序,并输入:
Enter number : 2↙
Enter exponent : 2↙
输出结果如下:
1
1.5
1.41667
1.41422
1. 41421
为了掌握函数的用法,我们再举两个函数应用的例子。第一个例子是关于有缺省参数的函数的用法:
|
|
例5-30 |
|
// 有缺省参数的函数 #include #include void de_fun(int i=5, long j=40034, float x=10.25, char ch='Z', double d=4.3234); // 函数原型
void main() { de_fun(); // 使用所有的缺省参数 de_fun(2); // 覆盖第一个缺省参数 de_fun(2, 75037); // 覆盖第一和第二个缺省参数 de_fun(2, 75037, 35.88); // 覆盖第一、第二和第三个缺省参数 de_fun(2, 75037, 35.88, 'G'); //覆盖第一、第二、第三和第四个缺省参数 de_fun(2, 75037, 35.88, 'G', .0023); // 未使用缺省参数 }
void de_fun(int i, long j, float x, char ch, double d) { cout << setprecision(4) << "i: " << i << " " << "j: " << j; cout << " x: " << x << " " << "ch: " << ch; cout << " d: " << d << "\n"; return; } |
|
上述程序的运行结果如下:
i: 5 j: 40034 x: 10.25 ch: Z d: 4.3234
i: 2 j: 40034 x: 10.25 ch: Z d: 4.3234
i: 2 j: 75037 x: 10.25 ch: Z d: 4.3234
i: 2 j: 75037 x: 35.88 ch: Z d: 4.3234
i: 2 j: 75037 x: 35.88 ch: G d: 4.3234
i: 2 j: 75037 x: 35.88 ch: G d: 0.0023
对de_fun()的每一次调用都产生了不同的结果,这是因为:在main函数中,每一次调用de_fun()均传送了不同的实参。
下面再看一个函数重载的例子,函数名为abs,其功能为求一个数的绝对值:
|
|
例5-31 |
|
// 重载两个绝对值函数. #include #include int abs(int i); // abs()重载三次 float abs(float x); float abs(double x);
void main() { int ians; // 保存返回值 float fans; double dans; int i = -15; // 传到三个重载的函数 float x = -64.53; double d = -120.293; ians = abs(i); // C++调用整数abs() cout << "整数-15的绝对值是 " << ians << "\n"; fans = abs(x); // C++调用单精度浮点abs() cout << "单精度浮点-64.53的绝对值是 " << setprecision(4) << fans << "\n"; dans = abs(d); // C++调用双精度浮点abs() cout << "双精度浮点-120.293的绝对值是 " << setprecision(6) << dans << "\n"; // 根据参数的类型,C++匹配有合适参数的函数 }
int abs(int i) // 整型绝对值函数 { if (i < 0) return i *( -1); else return i; }
float abs(float x) // 单精度浮点绝对值函数 { if (x < 0.0) return x * (-1.0); else return x; }
double abs(double x) // 双精度浮点绝对值函数 { if (x < 0.0) return x * (-1.0); else return x; } |
|
运行该程序,输出结果如下:
整数-15的绝对值是15
单精度浮点-64.53的绝对值是64.53
双精度浮点-120.293的绝对值是120.293
阅读(6778) | 评论(0) | 转发(1) |