【问题标题】:less than (<) comparison of float with if statement in c [duplicate]小于(<)float与c中if语句的比较[重复]
【发布时间】:2014-06-02 19:43:42
【问题描述】:

案例一

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

现在的问题是为什么?

【问题讨论】:

标签: c floating-point comparison


【解决方案1】:

我假设 float 是 IEEE 754 32 位二进制,double 是 IEEE 754 64 位二进制。

最接近 0.6(文字的实际值)的双精度数是 0.59999999999999997779553950749686919152736663818359375。转成float的结果是0.60000002384185791015625,稍微大一点。

最接近 0.9 的双精度数是 0.90000000000000002220446049250313080847263336181640625。转成float的结果是0.89999997615814208984375,稍微小一点。

在每种情况下,无法精确表示的小数会四舍五入到最接近的双精度数以表示文字。它被舍入为一个浮点数以分配给a,根据舍入到最近的规则,它可能比双精度略小或略大,或者如果双精度的二进制表示有很多尾随零,甚至可能完全相同.

【讨论】:

  • 那么关系运算符右轴上的 0.9 不应该也等于 0.89999997615814208984375 吗?如果是这样,那么它们不应该相等吗?
  • @Ganz7 0.9 是双精度数,而不是浮点数,因此其精确值为 0.90000000000000002220446049250313080847263336181640625。 float
  • 现在说得通了。我尝试在在线 IDE 上运行它,当我使用浮点文字 (0.9f) 或双精度 (0.9) 时没有区别。事实证明,某些硬件可能会将其转换为双精度,如本答案中所述,stackoverflow.com/a/7662210/991920
【解决方案2】:

将整个内容更改为仅使用单个文字,它应该始终有效

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.06.0 的不同截断可以使这两个算术表达式不同。但是,如果您编写了表达式(3.0*5.0 == 3.0*5.0),则对于任何符合要求的处理器始终保证为真。(注意,对于包括英特尔在内的许多处理器,您可以操纵配置,使其不符合 IEEE 浮点标准)

【讨论】:

  • 我试过了,但是输出还是一样
  • c# 是正确的结果,而不是 c,更重要的是对 0.9 的情况进行此修复
  • 精度损失,是这个原因!不正确的程序比强制的“正确”结果版本更具教育意义。浮点数不如双精度,因此如果分数不能精确地以二进制表示,则转换为双精度,可能意味着它比应有的小或大一点。在进行浮点比较时,避免丢失精度的转换并考虑舍入误差。
  • 一个更好的类比是折叠,'A'..'Z' 到 'k'..'o' 和 'a'..'z' 到 'o'..' 之间的随机字母k',然后将结果与'm'进行比较。结果告诉您原始输入介于 A..Z 和 a..z 之间,但与您开始时的不同。
【解决方案3】:

简短的回答:浮点数不能用二进制符号精确表示,即使它们有十进制的终止定义。这意味着将一个浮点数与另一个假设相等的浮点数进行比较,并不能保证任何一种方式都可以,一切都取决于架构和该架构上浮点数的表示。

【讨论】:

  • 明白了,谢谢你的帮助
  • b/w小于和等价比较有什么区别吗?
  • @Dios 不至于比较两个浮点数,以确保它们按预期工作。两者都依赖于二进制表示,因此两者都面临相同的问题。但是在示例中使用此精度范围内的浮点数时,两个不同值的不同浮点数之间的小于比较将按您的预期工作,而相等的比较可能不会。
  • 这个问题的正确答案不是“浮点数不精确,不要比较它们”。问题中没有浮点计算,对于给定的 C99 编译器,程序的结果是完全可以预测的。
  • 正确的答案是解释,精度是如何损失的 double (float(0.6)) != double (0.6)。常见的十进制小数的二进制表示不精确,如示例中的大部分内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-15
  • 1970-01-01
  • 2018-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多