【问题标题】:why if(a==2.3) evaluates false when float a=2.3 [duplicate]为什么当 float a=2.3 时 if(a==2.3) 评估为 false [重复]
【发布时间】:2016-09-21 12:21:35
【问题描述】:
#include<stdio.h>

void main()
{
    float a = 2.3;
    if(a == 2.3) {
        pritnf("hello");
    }
    else {
        printf("hi");
    }
}

它在输出中打印“hi”,或者我们可以说如果条件得到假值。

#include<stdio.h>

void main()
{
    float a = 2.5;
    if(a == 2.5)
        printf("Hello");
    else
        printf("Hi");
}

它打印你好。

【问题讨论】:

  • @dbush 我不同意这个骗局。假设的欺骗是关于浮点 computation 可能不精确,而这个问题是关于 floatdouble 常量。如果a 是不能表示整数常量的shortchar,也会出现同样的问题。
  • 那为什么会这样呢??
  • 阅读floating-point-gui.de(这个网址很重要,值得记住)

标签: c


【解决方案1】:

变量a 是一个float,它的值接近数学值2.3。

文字2.3 是一个double,它也拥有一些接近数学值2.3 的值,但因为double 的精度高于float,这可能与@987654327 的值不同@。 floatdouble 都只能表示有限数量的值,因此必然存在无法由这两种类型中的任何一种准确表示的数学实数。

在比较a == 2.3 中,左操作数从float 提升为double。此促销是准确的并保留了值(就像所有促销一样),但如上所述,该值可能与 2.3 文字的值不同。

要在浮点数之间进行比较,可以使用适当的浮点字面量:

assert(a == 2.3f);
//             ^

【讨论】:

  • 在 2.5 的情况下它计算它是真的吗?它是特定于编译器的吗??
  • 或者更确切地说......不要将==用于浮点值。
  • @pmg:我认为这太过分了。如果你知道它的含义和你在做什么,你可以使用相等比较。 OP 的情况是公然可以解决的(例如使用a == 2.3f),我不会说这很糟糕。重要的一点是不要假设精确的计算
  • @DombiSzabolcs:见我之前的评论。我不同意这种过于笼统的说法。我更喜欢理解而不是盲目坚持教条。
  • @Diti: C11 6.2.5, "Types" 表示float 表示的值集是double 表示的值的子集,Conversions 上的 6.3.1.5 表示如果一个值可以精确表示,那么结果值就是那个值。 (C 实际上并不使用术语“提升”来表示浮点值,但 C++ 会。)
【解决方案2】:

2.3 二进制表示为01000000000100110011001100110011... 所以您无法将浮点数精确设置为2.3 使用双精度,您会得到类似的结果:2.299999952316284

您在编写时将双精度数转换为浮点数:

float a = 2.3;

if 检查float a 是否等于double 2.299999952316284

你应该写:

float a = 2.3f;

你可以检查一下:

if (a == 2.3f) {
    ...
}

我宁愿测试:

if (fabs(a - 2.3f) < 0.00001) {
    ...
}

用位表示的2.5是:01000000001000000000000000000000

编辑: fabs&lt;math.h&gt;&lt;cmath&gt; 的一部分

阅读:article

【讨论】:

  • 使用十进制浮点数的实现当然可以准确地表示 2.3 和 2.5。这最终是实现定义的。重要的一点是 一些 值无法准确表示。
  • no 2.3 将需要无限位数。 C 语言从不使用浮点数的十进制表示,当您打印 2.3 时,它会显示一个四舍五入的数字。
  • @DombiSzabolcs:C11 标准草案 n1570:5.2.4.2.2 浮动类型的特征 1 浮动类型的特征是根据描述表示的模型定义的提供有关实现的浮点运算的信息的浮点数和值。 21) 以下参数用于定义每种浮点类型的模型: [...] b 指数表示的基数或基数(整数 > 1) 不要求 b 不等于10.
  • 有趣,我认为这些值将转换为IEEE_floating_points
  • @DombiSzabolcs:C 语言是在 60 年代末和 70 年代初开发的。 IEEE 754 二进制浮点标准于 1985 年建立。您认为 C 语言如何要求 IEEE 754?
【解决方案3】:

比较浮点值并不像看起来那么容易,请查看Most effective way for float and double comparison

这一切都归结为一个事实,浮点数并不精确(好吧 大多数不是)。通常你通过允许一个小的错误窗口(epsilon)来比较 2 个浮点数:

if( fabs(a - 2.3f) < epsion) { ... }

其中 epsilon 对于您的计算来说足够小,但不能太小(大于 Machine epsilon)。

【讨论】:

    猜你喜欢
    • 2012-02-20
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 2019-05-27
    • 1970-01-01
    相关资源
    最近更新 更多