二分法+牛顿迭代法+简化牛顿迭代法+牛顿下山法解方程的近似值

1、二分法

//求方程 2*x*x*x-4*x*x+3*x-6 的根
/* 二分法*/
#include<stdio.h>
#include<math.h>
#define Epsilon 1.0E-6//解的精度 
double func(double x) //函数
{
	return   2 * x * x * x - 4 * x * x + 3 * x - 6;
}
int main() {
	double x, y, x0, f1, f2, f0;
	printf("Please input the boundary of the value:");
	scanf("%lf%lf", &x, &y);// [x-x0-y] 
	x0 = (x + y) / 2;
	f0 = func(x0);
	f1 = func(x);
	f2 = func(y);
	while (fabs(f0) >= Epsilon)
	{
		if (f0 * f1 < 0)
		{
			y = x0;
			f2 = func(y);
		}
		if (f0 * f2 < 0)
		{
			x = x0;
			f1 = func(x);
		}
		x0 = (x + y) / 2;
		f0 = func(x0);
	}
	printf("用二分法求得方程的一个根:%f\n", x0);
}

在这里插入图片描述

2、牛顿迭代法

(Newton’s method)又称为牛顿-拉夫逊(拉弗森)方法(Newton-Raphson method),它是牛顿在17世纪提出的一种在实数域和复数域上近似求解方程的方法。在这里插入图片描述
百度百科–牛顿迭代法

2.1 普通的牛顿迭代法

//用牛顿迭代法 求方程 2*x*x*x-4*x*x+3*x-6 的根
/* 牛顿迭代法 */
#include<stdio.h>
#include<math.h>
//#define Epsilon 1.0E-6//解的精度 
double func(double x) //函数
{
    return 2 * x * x * x - 4 * x * x + 3 * x - 6.0;
}
double func1(double x) //导函数
{
    return 6 * x * x - 8 * x + 3;
}
double Newton() {
    double x0, x1 = 0.0, precision;// 可以选择1.0E-6为解的精度 
    printf("输入初始迭代值x0:");
    scanf("%lf", &x0);
    printf("迭代要求的精度:");
    scanf("%lf", &precision);
    x1 = x0 - func(x0) / func1(x0);
    while (fabs(x1 - x0) >= precision) {
        x0 = x1;
        x1 = x0 - func(x0) / func1(x0);
    }
    return x1;
}
int main() {
    double answer = Newton();
    if (answer != 0) {//可以直接看出答案不能为0,故作判断依据
        printf("%f", answer);
    }
}

在这里插入图片描述

2.2 定义迭代次数的牛顿迭代法

//用牛顿迭代法 求方程 2*x*x*x-4*x*x+3*x-6 的根
/* 牛顿迭代法 */
#include<stdio.h>
#include<math.h>
//#define Epsilon 1.0E-6//解的精度 
double func(double x) //函数
{
    return 2*x*x*x-4*x*x+3*x-6.0;
}
double func1(double x) //导函数
{
    return 6*x*x-8*x+3;
}
int Newton(double *x,double precision,int maxcyc)      //maxcyc  迭代次数
{
    double x1,x0;
    int k;
    x0=*x;
    for(k=0;k<maxcyc;k++)
    {
        if(func1(x0)==0.0)//若通过初值,函数返回值为0
        {
            printf("迭代过程中导数为0!\n");
            return 0;
        }
        x1=x0-func(x0)/func1(x0);//进行牛顿迭代计算
        if((fabs(x1-x0)<precision )|| (fabs(func(x1))<precision))//达到结束条件
        {
            *x=x1; //返回结果
            return 1;
        }
        else //未达到结束条件
        {
            x0=x1; //准备下一次迭代
        }
    }
    printf("迭代次数超过预期!\n"); //迭代次数达到,仍没有达到精度
    return 0;
}
 
int main()
{
    double x,precision;
    int maxcyc;
    printf("输入初始迭代值x0:");
    scanf("%lf",&x);
    printf("输入最大迭代次数:");
    scanf("%d",&maxcyc);
    printf("迭代要求的精度:");
    scanf("%lf",&precision);
    if(Newton(&x,precision,maxcyc)==1) //若函数返回值为1
    {
        printf("该值附近的根为:%lf\n",x);
    }
    else //若函数返回值为0
    {
        printf("迭代失败!\n");
    }
    return 0;
}

在这里插入图片描述在这里插入图片描述

3、简化牛顿法

就是简单的把导数用最开始的那个

3.1简化的牛顿法代码

//用牛顿迭代法 求方程 x^3- x-1=0的根
/* 简化牛顿法 */
#include<math.h>
#include<iostream>
using namespace std;
//#define Epsilon 1.0E-6//解的精度 
double func(double x) //函数
{
    return x * x * x - x * x - 1.0;
}
double func1(double x) //导函数
{
    return 3 * x * x - 2*x;
}
double Newton() {
    double x0, x1 = 0.0, precision;// 可以选择1.0E-6为解的精度 
    printf("输入初始迭代值x0:");
    cin >> x0;
    // printf("迭代要求的精度:");
     //cin >> precision;
    precision = 1.0E-6;
    double staticNum = func1(x0);
    x1 = x0 - func(x0) / func1(x0);
    while (fabs(x1 - x0) >= precision) {
        x0 = x1;
        x1 = x0 - func(x0) / staticNum;
        cout << func(x1) << " ";
    }
    return x1;
}

int main() {
    double answer = Newton();
    if (answer != 0)
        cout << answer << endl;

}

在这里插入图片描述

对比之前的牛顿法

//用牛顿迭代法 求方程 2*x*x*x-4*x*x+3*x-6 的根
/* 牛顿迭代法 */
#include<stdio.h>
#include<math.h>
//#define Epsilon 1.0E-6//解的精度 
double func(double x) //函数
{
    return x * x * x - x * x - 1.0;
}
double func1(double x) //导函数
{
    return 3 * x * x - 2*x;
}
double Newton() {
    double x0, x1 = 0.0, precision;// 可以选择1.0E-6为解的精度 
    printf("输入初始迭代值x0:");
    scanf("%f", &x0);
    // printf("迭代要求的精度:");
     //scanf("%f",&precision);
    precision = 1.0E-6;
    x1 = x0 - func(x0) / func1(x0);
    while (fabs(x1 - x0) >= precision) {
        x0 = x1;
        x1 = x0 - func(x0) / func1(x0);
        printf("%lf ", func(x1));
    }
    return x1;
}
int main() {
    double answer = Newton();
    if (answer != 0) {//可以直接看出答案不能为0,故作判断依据
        printf("%f", answer);
    }
}


已知在x=1.5附近有一个零点,所以
同时使用x0=1.5,对比收敛速度,明显知道之前没有简化的牛顿法比较慢
在这里插入图片描述
在这里插入图片描述

但是如果用0.6(一个偏离正确的值),会发现牛顿法可以求出而已。
在这里插入图片描述

4、牛顿下山法

4.1牛顿下山法代码

//用牛顿迭代法 求方程 x^3- x-1=0的根
/* 简化牛顿法 */
#include<math.h>
#include<iostream>
using namespace std;
//#define Epsilon 1.0E-6//解的精度 
double func(double x) //函数
{
    return x * x * x -  x * x -1.0;
}
double func1(double x) //导函数
{
    return 3 * x * x - 2*x;
}
double Newton() {
    double x,x1,precision;// 可以选择1.0E-6为解的精度 
    printf("输入初始迭代值x0:");
    cin >> x;
    precision = 1.0E-4;
    double y = func(x);
    double r=1.0;         //下山因子
    int time = 1;
    while (abs(y) > precision) {
        r = 1;
        x1 = x - r * y / (func1(x));
        cout << x1 << " ";
        while (  abs(func(x1)) > abs(func(x))  ) {
            r = r / 2;
            x1 = x - r * y / func1(x);
            cout << x1 << " ";
        }
        x = x1;
        y = func(x);
        time += 1;
    }   
    return x;
}

int main() {
    double answer = Newton();   
    if(answer!=0)
        cout << answer<<endl;

}


在这里插入图片描述

对比可以发现,牛顿下山法快一点,变化幅度小。

补充:关于评论区的问题

如何实现牛顿下山法的过程,抱歉,用C++,我能力有限,我了解到可以用opencv和EasyX Graphics Library库,但对我来说,人生苦短,我用python

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.pyplot import MultipleLocator

Epsilon = 1.0E-6
def func(x:float) :#函数
    return x * x * x - x * x - 1.0

def func1(x:float) :# 导函数
    return 3 * x * x - 2 * x

def Newton():
    x = eval(input("输入初始迭代值x0:")) # cin >> x;
    precision = Epsilon
    y = func(x)
    r = 1.0;         # 下山因子
    X_List = []
    while abs(y) > precision:
        r = 1
        x1 = x - r * y / (func1(x))
        X_List.append(x1)
        # print(x1) #cout << x1 << " ";
        while abs(func(x1)) > abs(func(x)) :
            r = r / 2
            x1 = x - r * y / func1(x)
            X_List.append(x1)
        x = x1
        y = func(x)
    return x, X_List

def main():
    answer, Y_List  = Newton()
    if answer != 0:
        print(answer) # cout << answer << endl
        X_List = [i+1 for i in range(len(Y_List))]    
        y_min,y_max = np.min(Y_List),np.max(Y_List)    
        my_y_ticks = np.arange(y_min,y_max,(-y_min+y_max)/len(X_List))
        plt.yticks(my_y_ticks)
        x_major_locator=MultipleLocator(1)
        # 把x轴的主刻度设置为1的倍数
        ax = plt.gca()
        ax.xaxis.set_major_locator(x_major_locator)
        plt.plot(X_List,Y_List,color='red', marker='o', linestyle='dashed', linewidth=1, markersize=5)
        plt.show()
main()

在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

广大菜鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值