二分法求取方程根
阿新 • • 發佈:2018-11-19
問題背景:本次我們來求取 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()
變化影象: