案例1
float a = 0.6;
if (a < 0.6)
{
printf("c");
}
else
{
printf("c#");
}
输出c#
案例2
float a = 0.9;
if (a < 0.9)
{
printf("c");
}
else
{
printf("c#");
}
输出c
现在问题是为什么?
答案 0 :(得分:7)
我假设float是IEEE 754 32位二进制文件,double是IEEE 754 64位二进制文件。
最接近的0.6,即文字的实际值,是0.59999999999999997779553950749686919152736663818359375。将其转换为浮动的结果是0.60000002384185791015625,略大一些。
最接近0.9的双倍是0.90000000000000002220446049250313080847263336181640625。将其转换为浮动的结果是0.89999997615814208984375,略小。
在每种情况下,无法精确表示的小数部分四舍五入到最接近的double表示文字。它被舍入到浮点数以分配给a
,它在圆形到最近的规则下可能略小或略大于双精度,或者如果双精度的二进制表示有很多,则可能完全相同尾随零。
答案 1 :(得分:0)
简短回答:浮点数无法用二进制表示法精确表示,即使它们具有十进制的终止定义。这意味着将浮点数与另一个浮点数(假设相等的浮点数)进行比较并不能保证两种方式,一切都取决于架构和该架构上浮点数的表示。
答案 2 :(得分:0)
将整个内容更改为仅使用单个文字,并且应该始终有效
float a = 0.6f;
if (a < 0.6f)
{
printf("c");
}
else
{
printf("c#");
}
错误实际上与准确性问题无关,而且与类型提升有关。这相当于将300
推入char
,然后将结果与实数300
进行比较。当你第一次推入它时,值被截断以适应较小的类型,并且在比较期间它被提升回更大的类型。
修改强>
每个人在这里谈论的准确性问题都是一个不同的现象。您可以使用布尔表达式(4.0*3.0 == 2.0*6.0)
清楚地看到它显示两个术语都是12.0
但3.0
和6.0
的不同截断可以使这两个算术表达式不同。但是,如果您编写了表达式(3.0*5.0 == 3.0*5.0)
,那么对于任何符合标准的处理器来说,这始终是正确的。(对于包括intel在内的许多处理器,您可以操纵配置,使它们不符合IEEE浮点数标准)