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世纪提出的一种在实数域和复数域上近似求解方程的方法。

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


​百度百科–牛顿迭代法​

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);
}
}

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

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;
}

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

二分法+牛顿迭代法+简化牛顿迭代法+牛顿下山法解方程的近似值_开发语言_05

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;

}

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

对比之前的牛顿法

//用牛顿迭代法 求方程 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,对比收敛速度,明显知道之前没有简化的牛顿法比较慢

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


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

但是如果用0.6(一个偏离正确的值),会发现牛顿法可以求出而已。

二分法+牛顿迭代法+简化牛顿迭代法+牛顿下山法解方程的近似值_开发语言_09

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;

}

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

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

补充:关于评论区的问题

如何实现牛顿下山法的过程,抱歉,用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()

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