浮點數不能精確比較
藍橋杯例題1:
浮點數:對它的說法是足夠接近 |a - b| < seta,而不是完全相等(不能用 == 來判斷,這是大忌)。因爲計算式內部是採用二進制的方式來表示。
上題可以用暴力破解法,
for (int a = 0; a < 100 ; a++) //a 是啤酒數量,b是飲料的數量,假設它們的取值範圍都在0 ~ 100
{
for (int b = 0; b < 100; b++)
{
if (a * 2.3 + b * 1.9 == 82.3) printf("%d , %d \n",a,b);
}
}
但關於浮點運算,用以上的暴力破解法存在隱患,可用以下方法進行改善 (避開浮點數)。
避開浮點數:價錢都是以元爲單位,存在小數,那麼全都乘10倍,改成以角爲單位。
for (int a = 0; a < 100 ; a++)
{
for (int b = 0; b < 100; b++)
{
if (a * 23 + b * 19 == 823) printf("%d , %d \n",a,b);
}
}//雖然與前一種方法沒什麼差別,但避開浮點數,可以有效的避開題目中或許隱含着的陷阱。
藍橋杯例題2:
【注意】
寫成16行那樣是錯誤的:因爲1/XXX得到的答案都0
寫成17行那樣可行,可是對於浮點運算用了 == 進行比較,雖然能得出正確結論,但存在隱患
解決存在的隱患:
1). 寫成17行那樣,但進行比較時不用==,而是用 abs (1.0/a + 1.0/b + 1.0/c + 1.0/d - 1.0) < 1E-10(或其他小數)進行比較。
2).寫成18行那樣,用通分的方法,解決存在分母的問題,等式兩邊同乘上 abcd(要注意是否超過整型範圍)。
浮點數:一般我們表示的都是有理數。 有理數的表示:分子/分母。
浮點數運算時目前採用的規則是IEEE754,該規則規定浮點數有幾個特殊的值:(double類型)
- Infinity 無窮大 ,如double a = 3.0 / 0 可得到的值
- 減號 Infinity 負無窮大
- 0.0 ,如 1/a 可取得
- 減號 0.0,如1/(-a) NAN:Not a Number ,無意義,如a/a,a-a 都可得到
如例題:要求有效數字100位,即任意精度的小數。
浮點數的四捨五入模式:四捨六入五成雙。
比如有浮點數3.150,捨去則是3.1,加入則是3.2,所以最後的結果是3.2,成雙。