牛顿迭代法定义如下(来自百度百科):
用牛顿迭代法小试牛刀用来求解一元二次方程的根(工程下载地址【注:不好意思,下载题目写成了二元一次方程,见谅。】,release下的应用程序可以直接运行),代码如下:
typedef struct _MyP
{
float x;
float y;
}MyP;
// C++实现牛顿迭代法求一元二次方程的解
// 设一元二次方程的通用方程为 y = ax^2 + bx + c
// 则其导函数为 y = 2ax + b
// 1、构造方程
float accuracy = 0.001;
float a = -5;
float b = 4;
float c = 0;
// 2、找极值点,令导函数 y = 2ax + b = 0,求的极值点坐标P.x = -b/2a, P.y = aP.x^2 + bP.x + c
MyP P;
MyP PTemp;
P.x = (-1 * b) / (2 * a);
P.y = (a * P.x * P.x) + (b * P.x) + c;
// 3、判断定义域在(-无穷大, P.x)和在定义域(P.x, +无穷大)的单调性和开口方向
PTemp.x = P.x - 10;
PTemp.y = (a * PTemp.x * PTemp.x) + (b * PTemp.x) + c;
if (PTemp.y > P.y){ // 在(-无穷大, P.x)单调递减,在(P.x, +无穷大)单调递增,开口向上
ui.tbResult->append(QString::fromLocal8Bit("开口方向:向上"));
// 4.1、判断方程是否有解,有解的话几个解
if (P.y > 0){
ui.tbResult->append(QString::fromLocal8Bit("解集情况:无解"));
}
else if (P.y == 0){
ui.tbResult->append(QString::fromLocal8Bit("解集情况:1个解"));
ui.tbResult->append(QString::fromLocal8Bit("解1:") + QString("(%1, %2)").arg(P.x).arg(P.y));
}
else{
ui.tbResult->append(QString::fromLocal8Bit("解集情况:2个解"));
// 5.1、牛顿迭代求解
float k; // 切点斜率
MyP P1, P2;
P1.x = P.x + accuracy; // 设置迭代起始点1
P2.x = P.x - accuracy; // 设置迭代起始点2
float x1, x2; // 解1和解2
while(1){
k = (2 * a * P1.x) + (b); // 求切点斜率
x1 = P1.x - (P1.y / k); // 切线与X轴的交点的x坐标
P1.y = (a * x1 * x1) + (b * x1) + c; // 求x1在一元二次方程曲线上的Y值
if (fabs(P1.y) <= 0.001){
if (x1 < accuracy) x1 = 0;
if (P1.y < accuracy) P1.y = 0;
ui.tbResult->append(QString::fromLocal8Bit("解1:") + QString("(%1, %2)").arg(x1).arg(P1.y));
break;
}
P1.x = x1; // 更新迭代点
}
while(1){
k = (2 * a * P2.x) + (b); // 求切点斜率
x2 = P2.x - (P2.y / k); // 切线与X轴的交点的x坐标
P2.y = (a * x2 * x2) + (b * x2) + c; // 求x1在一元二次方程曲线上的Y值
if (fabs(P2.y) <= 0.001){
if (x2 < accuracy) x2 = 0;
if (P2.y < accuracy) P2.y = 0;
ui.tbResult->append(QString::fromLocal8Bit("解2:") + QString("(%1, %2)").arg(x2).arg(P2.y));
break;
}
P2.x = x2; // 更新迭代点
}
}
}
else{ // 在(-无穷大, P.x)单调递增,在(P.x, +无穷大)单调递减,开口向下
ui.tbResult->append(QString::fromLocal8Bit("开口方向:开口向下"));
// 4.2、判断方程是否有解,有解的话几个解
if (P.y < 0){
ui.tbResult->append(QString::fromLocal8Bit("解集情况:无解"));
}
else if (P.y == 0){
ui.tbResult->append(QString::fromLocal8Bit("解集情况:1个解"));
ui.tbResult->append(QString::fromLocal8Bit("解1:") + QString("(%1, %2)").arg(P.x).arg(P.y));
}
else{
ui.tbResult->append(QString::fromLocal8Bit("解集情况:2个解"));
// 5.2、牛顿迭代求解
float k; // 切点斜率
MyP P1, P2;
P1.x = P.x + accuracy; // 设置迭代起始点1
P2.x = P.x - accuracy; // 设置迭代起始点2
float x1, x2; // 解1和解2
while(1){
k = (2 * a * P1.x) + (b); // 求切点斜率
x1 = P1.x - (P1.y / k); // 切线与X轴的交点的x坐标
P1.y = (a * x1 * x1) + (b * x1) + c; // 求x1在一元二次方程曲线上的Y值
if (fabs(P1.y) <= 0.001){
if (x1 < accuracy) x1 = 0;
if (P1.y < accuracy) P1.y = 0;
ui.tbResult->append(QString::fromLocal8Bit("解1:") + QString("(%1, %2)").arg(x1).arg(P1.y));
break;
}
P1.x = x1; // 更新迭代点
}
while(1){
k = (2 * a * P2.x) + (b); // 求切点斜率
x2 = P2.x - (P2.y / k); // 切线与X轴的交点的x坐标
P2.y = (a * x2 * x2) + (b * x2) + c; // 求x1在一元二次方程曲线上的Y值
if (fabs(P2.y) <= 0.001){
if (x2 < accuracy) x2 = 0;
if (P2.y < accuracy) P2.y = 0;
ui.tbResult->append(QString::fromLocal8Bit("解2:") + QString("(%1, %2)").arg(x2).arg(P2.y));
break;
}
P2.x = x2; // 更新迭代点
}
}
}
开发环境为VS2013+QT580+OPENCV300,软件运行截图如下:
工程中的release下的应用程序可以直接运行,需要软件和代码工程的请戳这里。