上一篇提到的都是整数情况下的二分查询问题,事实上二分法的应用远远不止此,下面介绍几个相关的例子。
例1 :如何计算 2 \sqrt{2} 2的近似值?
对 f ( x ) = x 2 \ f(x)=x^{2} f(x)=x2来说,在 x ∈ [ 1 , 2 ] \ x\in[1,2] x∈[1,2] 的范围内, f ( x ) \ f(x) f(x)是随着 x \ x x 的增大而增大的,这就给二分法创造了条件,由于 2 \sqrt{2} 2 是无理数,因此只能获得它的近似值,这里不妨以精度到 1 0 − 5 \ 10^{-5} 10−5 为例来逼近 2 \sqrt{2} 2。
首先,令浮点型 left 和 right 的初值分别为1和2,然后通过比较 left 和 right 的中点 mid 处 f ( x ) \ f(x) f(x) 的数值与2的大小来选择子区间进行逼近。有以下两种情况:
(1)如果 f ( m i d ) > 2 \ f(mid) > 2 f(mid)>2,说明 m i d > 2 \ mid > \sqrt{2} mid>2,应当在 [ l e f t , m i d ] \ [left, mid] [left,mid]的范围内继续逼近,故令 r i g h t = m i d \ right = mid right=mid。
(2)如果 f ( m i d ) < 2 \ f(mid) < 2 f(mid)<2,说明 m i d < 2 \ mid < \sqrt{2} mid<2,应当在 [ l e f t , m i d ] \ [left, mid] [left,mid]的范围内继续逼近,故令 l e f t = m i d \ left = mid left=mid。
当 r i g h t − l e f t < 1 0 − 5 \ right - left < 10^{-5} right−left<10−5 时结束,此时已经满足精度要求, m i d \ mid mid 即为所求的近似值。
具体实现代码如下:
#include<stdio.h>
const double eps = 1e-5;
double f(double x) {
return x * x;
}
double calSqrt() {
double left = 1, right = 2, mid;
while(right - left > eps) {
mid = (left + right) / 2;
if(f(mid) > 2) {
right = mid;
}
else {
left = mid;
}
}
return mid;
}
int main(){
printf("%f", calSqrt());
return 0;
}
未完待续…