今天做題遇到了一個題目,怎麼也ac不了,最後發現是精度(浮點誤差)的問題。
衆所周知,浮點數無論是double還是float都有精度限制,但它能存儲多少有效位數不代表它能精確到這些有效位數。比方說,你輸入一個1,float型可能存了1.000000001,也可能存了0.999999999,他們在輸出時都表示爲1,但在計算時不同。
比方說下述代碼二者結果一個爲0.00,一個爲0.01。
這種影響在0時表現尤爲明顯,十分影響a==0或a==b的判斷。
針對這種問題,我們可以設一個eps=1e-6(或者1e-8)用來檢驗,比方說:
aa-b<-eps a<=b–>eps
a==b–>abs(a-b)
int main()
{
printf("%.2f\n",0.0049);
printf("%.2f\n",0.0051);
return 0;
}
cugboj題目1524:解方程
有一個型爲 的一元二次方程,(a不等於0)你的任務是,編寫一個程序,實現輸入a,b,c三個整數後,輸出方程的解。
input:輸入第一行爲一個正整數N(1<=N<=50),爲測試數據的個數。 接下來N行每行包括三個整數a、b、c。
output:每個輸出佔一行,爲方程的解。 若方程有兩個相等的解,輸出一個即可。 若方程有兩個不等的解,先輸出值大的解,兩解以一個空格隔開。 若方程在實數範圍無解,輸出含虛數的解。
附上ac代碼():
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cmath>
using namespace std;
#define eps 1e-6
void ergen(int a,int b,int c);
void dangen(int a,int b,int c);
void xugen(int a,int b,int c);
int main()
{
double n,a,b,c;
cin>>n;
while(n--)
{
cin>>a>>b>>c;
if(b*b-4*a*c>eps) ergen(a,b,c);
else if(b*b-4*a*c<eps&&b*b-4*a*c>-eps) dangen(a,b,c);
else xugen(a,b,c);
}
return 0;
}
void xugen(int a,int b,int c)
{
double delta=4*a*c-b*b;
if(b!=0) printf("%.3lf+",-b*1.0/(2*a)+eps);
printf("%.3lfi ",abs(sqrt(delta)/(2*a))+eps);
if(b!=0) printf("%.3lf",-b*1.0/(2*a)+eps);
printf("-%.3lfi\n",abs(sqrt(delta)/(2*a))+eps);
}
void dangen(int a,int b,int c)
{
printf("%.3lf\n",-b*1.0/(2*a)+eps);
}
void ergen(int a,int b,int c)
{
double x1=(-b*1.0+sqrt(b*b-4.0*a*c))/(2*a)+eps;
double x2=(-b*1.0-sqrt(b*b-4.0*a*c))/(2*a)+eps;
printf("%.3lf %.3lf\n",max(x1,x2),min(x1,x2));
}