重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
#include stdio.h
创新互联公司于2013年创立,先为渝北等服务建站,渝北等地企业,进行企业商务咨询服务。为渝北企业网站制作PC+手机+微官网三网同步一站式服务解决您的所有建站问题。
#define PRECISION 0.000001
#define ABS(x) ((x) 0 ? -(x) : (x))
double sqr(double x) {
double g = x;
if (g 0) {
while (ABS(g*g-x) PRECISION) {
g = (g + x/g) / 2;
}
return g;
} else {
return 0;
}
}
/* delta法解2次方程 */
int delta_2(double A, double B, double C, double sols[]) {
double delta = B * B - 4 * A * C;
if (ABS(A) PRECISION) {
if (ABS(delta) PRECISION) { /* delta == 0 */
sols[0] = -B / (2 * A);
return 1;
} else if (delta 0) {
sols[0] = (-B - sqr(delta)) / (2 * A);
sols[1] = (-B + sqr(delta)) / (2 * A);
return 2;
} else {
return 0;
}
} else {
if (ABS(B) PRECISION) { /* 表达式为常数,即 A = B = 0,无解 */
return 0;
} else { /* 返回一元一次方程的根 */
sols[0] = -C / B;
return 1;
}
}
}
/* 牛顿法解3次方程 */
int newton_3(double args[], double sols[]) {
double A=args[0], B=args[1], C=args[2], D=args[3];
double x0[3];
int x0_num = 0;
double drts[2]; /* 此方程的导数的根 */
int drt_num = 0;
int i, j, limit_count = 100; /* 限制最多100次迭代,防止无解情况 */
double x = 0, xn = 0; /* 选x初值为0 */
double yl = 0, yr = 0;
/* 判断根的数量,现获取导数的根,即为三次方程的转向点 */
drt_num = delta_2(3 * A, 2 * B, C, drts);
if (drt_num == 0) { /* 导数无实根,没有 */
x0_num = 1;
x0[0] = 0;
} else if (drt_num == 1) {
x0_num = 1;
x0[0] = drts[0] + 1;
} else if (drt_num == 2) {
x = drts[0];
yl = A*x*x*x + B*x*x + C*x + D;
x = drts[1];
yr = A*x*x*x + B*x*x + C*x + D;
if (ABS(yl * yr) PRECISION) {
x0_num = 2;
x0[0] = drts[0] - 1;
x0[1] = drts[1] + 1;
} else if (yl * yr 0) {
x0_num = 1;
if (A * yl 0) {
x0[0] = drts[0] - 1;
} else {
x0[0] = drts[1] + 1;
}
} else {
x0_num = 3;
x0[0] = drts[0] - 1;
x0[1] = (drts[0] + drts[1]) / 2;
x0[2] = drts[1] + 1;
}
} else { /* 导数的二次系数为0,即函数的三次系数为0,所以不是三次函数,返回二次结果 */
return delta_2(B, C, D, sols);
}
for (j = 0; j x0_num; j++) {
for (i = 0, x = x0[j]; i limit_count; i++) {
xn = x - (A * x*x*x + B * x*x + C * x + D) / (3 * A * x*x + 2 * B * x + C);
if (xn - x PRECISION x - xn PRECISION) {
break;
}
x = xn;
}
sols[j] = xn;
}
return x0_num;
}
int main() {
double solutions[3]; /* 最多3个解 */
int i;
int sol_num = 0;
double args[] = {3, 6.1407188500, -7, -15}; /* 3次方程的4个系数,Ax^3 + Bx^2 + Cx + D ,在这里设置ABCD */
if ((sol_num = newton_3(args, solutions)) 0) {
printf("共有%d个解:\n", sol_num);
for (i = 0; i sol_num; i++) {
printf("x%d=%lf\n", i+1, solutions[i]);
}
} else {
puts("方程无解");
}
return 0;
}
先接代码吧,然后解释一下里面的函数:
newton_3 是用牛顿迭代法求三次函数的解,三次函数的解有三种情况:(1)有一个根 (2)有两个根 (3)有三个根。根据数学关系来进行了各种情况的判断。有一个根有两种情况,分别是导数恒大于等于零和“导数等于0”的两个根的函数值在X轴的同侧;有两个根的情况就是“导数等于0”的其中一个根和X轴相切;三个跟的情况就是“导数等于0”的两个根的函数值在X轴两侧。
delta_2 函数是用Δ法求二次函数的解,有三种情况:(1)无实根 (2)有一个实根 (3)有两个实根。
sqr 是用牛顿迭代法计算平方根的运算。math.h里面有sqrt可以实现,但是如果只因这个函数而引用math.h有点不值得,正好这道题目是牛顿迭代法的,这里正好写一个。
上面的代码可以解任何一元三次以内的函数的方程根。但是用来做你的问题,其实没有这么复杂,下面的代码就可以了,和上面的sqr的实现差不多。
#include stdio.h
#define PRECISION 0.000001
#define ABS(x) ((x) 0 ? -(x) : (x))
double sancigenhao(double y) {
double x0 = y, x;
while (1) {
x = x0 - (x0 * x0 * x0 - y) / (3 * x0 * x0);
if (ABS(x - x0) PRECISION) {
return x;
}
x0 = x;
}
}
int main() {
printf("x=%lf\n", sancigenhao(155));
return 0;
}
两个方法都可以,用前面的通用方法,就把 A B C D 分别填写 1 0 0 -155,就能得出解来。但是后面的方法用来解三次根号要简单多了
#include "stdio.h"
#include "math.h"
main()
{float x,f,f1; //f代表 f(x)=2x^3-4x^2+5x-18,f1代表 f‘(x)=2*x^2-4*2x^+5 =6*x*x-8*x+5;
x=8; // x的初值可为任意值
do
{
f=2*x*x*x-4*x*x+5*x-18; //f(x)=2x3-4x2+5x-18
f1=6*x*x-8*x+5; //f(x)的导数: f‘(x)=2*3* x^2 - 4*2 *x+5 =6*x*x-8*x+5;
x=x-f/f1;
}while(fabs(f)0.00001);
printf("x=%f,f=%f\n",x,f);
}
#includestdio.h
#includemath.h
int main()
{
float x1,x,f1,f2;static int count=0;
x1=1.5//定义初始值
do
{
x=x1;
f1=x*(2*x*x-4*x+3)-6;
f2=6*x*x-8*x+3;//对函数f1求导
x1=x-f1/f2; count++;
}while(fabs(x1-x)=1e-5);
printf("%8.7f\n",x1); printf("%d\n",count);
return 0;
}
//2x3-4x2+3x-6//根据我改了初始值,查看结果,表明:改变初始值得到的结果并不一样,但是迭代的次数并没有改变!!
给你一点提示。
牛顿迭代法要计算
(1) y1=f(x) 在 x 的函数值
(2) d1=f(x) 的一阶导数 在 x 的值
你可以写两个函数,分别计算y1,d1
如果一阶导数有解析解,则可用赋值语句,否则要写数值解子程序。
步骤:
设解的精度,例 float eps=0.000001;
设x初值,x1;
算y1=f(x1);
迭代循环开始
算一阶导数 在 x1 的值 d1
用牛顿公式 算出 x2; [x2 = x1 - y1 / d1]
如果 fabs(x2-x1) eps 则从新迭代 -- 用新的函数值和一阶导数值推下一个 新x.
#includestdio.h
#includemath.h
int a,b,c,d;
float f(float x)
{ float y;
y=((a*x+b)*x+c)*x+d;
return(y);
}
float f1(float x)
{ float y;
y=(3*a*x+2*b)*x+c;
return(y);
}
void main()
{ float x0=1.0,x1;
printf("请输入a,b,c,d的值:\n");
scanf("%d,%d,%d,%d",a,b,c,d);
x1=1;
do
{
x0=x1;
x1=x0-f(x0)/f1(x0);
}
while(fabs(x1-x0) =0.00001);
printf("%f",x1);
}
牛顿迭代法:
牛顿迭代法(Newton's method)又称为牛顿-拉弗森方法(Newton-Raphson method),它是一种在实数域和复数域上近似求解方程的方法。方法使用函数的泰勒级数的前面几项来寻找方程的根。