二分法求取方程根

版权声明:博主的博客不值钱随便转载但要注明出处 https://blog.csdn.net/easylovecsdn/article/details/84112101

问题背景:本次我们来求取 f(x) = -2x^3 + 5x^2 + 9,这个函数,在给定区间[2, 4]上的零点。

解决方法:二分法

编程语言:c++、python

说明:这里将分别使用两种编程语言和3种二分法的终止条件来完成二分的求解。

函数图像:

二分的终止条件:

1.区间小于某标准值

2.循环次数

3.真实误差小于某值 |(Xnew - Xold) / Xnew| * 100%

流程图:(偷个懒我这里之画一个)

c++篇

1.循环次数

//凭借循环次数来终止二分

#include <iostream>
#include <cstdio>

using namespace std;

const int maxn = 9999;

double f(double x)
{
    return -2 * x * x * x + 5 * x * x + 9;
}

int main()
{
    double a = 2;         //卡取两个端点值
    double b = 4;
    double mid;


    if (f(a) > 0)         //区间增函数
    {
        for (int i = 0; i <= maxn; i++)
        {
            mid = (a + b) / 2;

            if (f(mid) == 0) break;

            if (f(mid) > 0) a = mid;
            else b = mid;

        }
    }
    else                  //区间减函数
    {
        for (int i = 0; i <= maxn; i++)
        {
            mid = (a + b) / 2;

            if (f(mid) == 0) break;

            if (f(mid) > 0) b = mid;
            else a = mid;

        }
    }


    printf("f(%.3lf) = %.3lf\n", mid, f(mid));
    return 0;
}

2.区间小于某标准值

//区间小于某值来终止二分

#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

const double board = 1e-2;

double f(double x)
{
    return -2 * x * x * x + 5 * x * x + 9;
}

int main()
{
    double a = 2;         //卡取两个端点值
    double b = 4;
    double mid;


    if (f(a) > 0)         //区间增函数
    {
        while (fabs(a - b) >= board)
        {
            mid = (a + b) / 2;

            if (f(mid) == 0) break;

            if (f(mid) > 0) a = mid;
            else b = mid;

        }
    }
    else                  //区间减函数
    {
        while (fabs(a - b) >= board)
        {
            mid = (a + b) / 2;

            if (f(mid) == 0) break;

            if (f(mid) > 0) b = mid;
            else a = mid;

        }
    }


    printf("f(%.3lf) = %.3lf\n", mid, f(mid));
    return 0;
}

3.真实误差小于某值

//真实误差小于某值来终止二分

#include <iostream>
#include <cstdio>
#include <cmath>

#define     INF     0x3f3f3f3f

using namespace std;

const double rate = 1e-2;

double f(double x)
{
    return -2 * x * x * x + 5 * x * x + 9;
}

int main()
{
    double a = 2;    //卡取两个端点值
    double b = 4;
    double mid, r = INF;

    if (f(a) > 0)    //区间增函数
    {
        while (r > rate)
        {
            mid = (a + b) / 2;

            if (f(mid) == 0) break;

            if (f(mid) > 0)
            {
                r = fabs((mid - a) / a);
                a = mid;
            }
            else
            {
                r = fabs((mid - b) / b);
                b = mid;
            }

        }
    }
    else   //区间减函数
    {
        while (r > rate)
        {
            mid = (a + b) / 2;

            if (f(mid) == 0) break;

            if (f(mid) > 0)
            {
                r = fabs((mid - b) / b);
                b = mid;
            }
            else
            {
                r = fabs((mid - a) / a);
                a = mid;
            }

        }
    }


    printf("f(%.3lf) = %.3lf\n", mid, f(mid));
    return 0;
}

python篇

1.循环次数

# -*- coding: utf-8 -*-

#最大循环次数
maxn = 9999

#定义函数f(x)
def f(x):
    return -2.0 * x**3 + 5.0 * x**2 + 9.0

#规定两区间端点
a = 2.0
b = 4.0

#进行二分
if f(a) > 0 :
    for i in range(maxn) :
        
        mid = (a + b) / 2;
        
        if f(mid) == 0 : break
        
        if f(mid) > 0 : a = mid
        else : b = mid
else :
    for i in range(maxn) : 
        
        mid = (a + b) / 2;
        
        if f(mid) == 0 : break
        
        if f(mid) > 0 : b = mid
        else : a = mid
 
#输出结果       
print("f(%.3lf) = %.3lf\n" %(mid, f(mid)))
            

2.区间小于某标准值

# -*- coding: utf-8 -*-


import math

#定义边界
board = 1e-2

#定义函数f(x)
def f(x):
    return -2.0 * x**3 + 5.0 * x**2 + 9.0

#规定两区间端点
a = 2.0
b = 4.0

#进行二分
if f(a) > 0 :
    while math.fabs(a - b) >= board :
        
        mid = (a + b) / 2;
        
        if f(mid) == 0 : break
        
        if f(mid) > 0 : a = mid
        else : b = mid
else :
    while math.fabs(a - b) >= board : 
        
        mid = (a + b) / 2;
        
        if f(mid) == 0 : break
        
        if f(mid) > 0 : b = mid
        else : a = mid
 
#输出结果       
print("f(%.3lf) = %.3lf\n" %(mid, f(mid)))
            

3.真实误差小于某值

# -*- coding: utf-8 -*-


import math

#定义误差率,与最大值
rate = 1e-2
INF = 0x3f3f3f3f

#定义函数f(x)
def f(x):
    return -2.0 * x**3 + 5.0 * x**2 + 9.0

#规定两区间端点
a = 2.0
b = 4.0

r = INF

#进行二分
if f(a) > 0 :
    while r > rate :
        
        mid = (a + b) / 2;
        
        if f(mid) == 0 : break
        
        if f(mid) > 0 : 
            r = math.fabs((mid - a) / a)
            a = mid
        else : 
            r = math.fabs((mid - b) / b)
            b = mid
else :
    while r > rate : 
        
        mid = (a + b) / 2;
        
        if f(mid) == 0 : break
        
        if f(mid) > 0 : 
            r = math.fabs((mid - b) / b)
            b = mid
        else : 
            r = math.fabs((mid - a) / a)
            a = mid
 
#输出结果       
print("f(%.3lf) = %.3lf\n" %(mid, f(mid)))
            

mid的变化趋势:
为了使变化折线明显这里将区间段点值改为[1, 3.9]

图像生成代码:


# -*- coding: utf-8 -*-


import numpy as np
import matplotlib.pyplot as plt

plt.figure(1)
 
#最大循环次数
maxn = 9999
 
#定义函数f(x)
def f(x):
    return -2.0 * x**3 + 5.0 * x**2 + 9.0
 
#规定两区间端点
a = 1.0
b = 3.9

#图像生成所需要的集合
m = []
n = []

scope = np.linspace(2, 4, 100)

 
#进行二分
if f(a) > 0 :
    for i in range(maxn) :
        
        mid = (a + b) / 2;
        
        m.append(mid)
        n.append(f(mid))
        
        if f(mid) == 0 : 
            break
        
        if f(mid) > 0 : 
            a = mid
        else : 
            b = mid
else :
    for i in range(maxn) : 
        
        mid = (a + b) / 2;
        
        if f(mid) == 0 : 
            break
        
        if f(mid) > 0 : 
            b = mid
        else : 
            a = mid
 
#输出结果       
print("f(%.3lf) = %.3lf\n" %(mid, f(mid)))

#生成图像
plt.plot(m, n)
plt.show()
            

变化图像: 

猜你喜欢

转载自blog.csdn.net/easylovecsdn/article/details/84112101
今日推荐