《一元三次方程求解》牛顿迭代解法
一元三次方程求解
http://www.nowcoder.com/questionTerminal/ed2ece368ae94c36968478b6f9ba79c8
这道题的标准解法是使用二分查找,题目给出了如何判定区间内是否有根的提示,即则在
之间一定有一个根。
但是如果借助微积分技巧,这道题还可以有另外一种解法。
首先,我们考虑若三次函数在
区间存在三个实根,那么该函数在该区间内必定存在两个顶点,即其导数
在该区间内有两个实根
,其中
,我们可以使用一元二次方程求根公式分别求出,求根公式为:
根据导数的性质,我们可以确定的三个根分别位于区间
、
和
内。于是我们可以在这三个区间内分别使用牛顿迭代法进行求根。其中牛顿迭代法公式为:
迭代的初始值可以设定为该区间的中点,一般每个区间两三次迭代即可完成。
代码如下:
#include <iostream> #include <cmath> #include <iomanip> using namespace std; double a, b, c, d; const double eps = 1e-3; double f(double x) { //求f(x)的值 return a * x * x * x + b * x * x + c * x + d; } double fp(double x) { //求导数f'(x)的值 return 3 * a * x * x + 2 * b * x + c; } double newton(double x0) { //牛顿迭代,精度为1e-3 double x = x0; do { x0 = x; x = x0 - f(x0) / fp(x0); } while (abs(x - x0) > eps); return x; } int main() { cin >> a >> b >> c >> d; //求导数f'(x)的两个根,即函数f(x)的两个顶点 double delta = sqrt(b * b - 3 * a * c); double xp1 = (-b - delta) / (a * 3); double xp2 = (-b + delta) / (a * 3); //分别对三个区间使用牛顿迭代求根 double x1 = newton(-100 + (xp1 + 100) / 2); double x2 = newton(xp1 + (xp2 - xp1) / 2); double x3 = newton(xp2 + (100 - xp2) / 2); cout << fixed << setprecision(2) << x1 << " " << x2 << " " << x3; }