浮点数二分

1
2
3
4
5
6
7
8
9
10
11
double l=0,r=n;
while(r-l>1e-6){//若要求n位小数,最好为1e-(n+2)
double mid=(l+r)/2;
if(check(mid)){//判断mid是否属于右区间
r=mid;
}
else{
l=mid;
}
}
return l;//l=r,返回l,r均可

例题:给定$a,b,c,d$,求$ax^3+bx^2+cx+d=0$ 的三个根(保证$-100\le x_1<x_1+1\le x_2<x_2+1\le x_3\le100$),保留两位小数

分析:题目保证每两个根之差大于等于$1$,则可以从$-100$枚举到$100$,每次判断长度为$1$的区间,若端点的函数值之积小于$0$,则此区间必有一个根,二分求根($check:mid,r$的函数值之积小于$0$)

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<bits/stdc++.h>
using namespace std;

double a,b,c,d;

double count(double x){
return a*x*x*x+b*x*x+c*x+d;
}

void find(double l,double r){
while(r-l>1e-4){
double mid=(l+r)/2;
if(count(mid)*count(r)<=0){
l=mid;
}
else{
r=mid;
}
}
cout << fixed << setprecision(2) << l << ' ';
}

int main(){
cin >> a >> b >> c >> d;
for(int i=-100;i<100;i++){
if(count(i)==0){
cout << fixed << setprecision(2) << 1.0*i << ' ';
}
else if(count(i)*count(i+1)<0)find(i,i+1);
}
return 0;
}