浮点数不能精确比较
蓝桥杯例题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,成双。