1

根据这篇文章,当比较浮点数和双精度时,浮点数应被视为双精度。下面的程序,似乎没有遵循这个说法。这种行为看起来非常不可预测。这是我的程序:

void main(void)
{
    double a = 1.1;  // 1.5
    float b = 1.1;   // 1.5
    printf("%X  %X\n", a, b);
    if ( a == b)
        cout << "success " <<endl;
    else
        cout << "fail" <<endl;
}
  • 当我运行以下程序时,显示“失败”。
  • 但是,当我将 a 和 b 更改为 1.5 时,它显示“成功”。

我还打印了值的十六进制表示法。在这两种情况下它们是不同的。我的编译器是 Visual Studio 2005

你能解释一下这个输出吗?谢谢。

4

4 回答 4

10
float f = 1.1;
double d = 1.1;
if (f == d)

在此比较中, 的值f被提升为 type double。您看到的问题不在于比较,而在于初始化。1.1不能完全表示为浮点值,因此存储在fd中的值是可以表示的最接近的值。但是floatdouble是不同的大小,因此具有不同数量的有效位。当 in 的值f提升为double时,无法取回在存储该值时丢失的额外位,因此您最终会在额外位中得到全零。那些零位与 中的位不匹配d,因此比较是错误的。比较成功的原因1.51.5 可以精确地表示为float并作为double; 它的低位有一堆零,因此当促销添加零时,结果与double表示相同。

于 2013-06-27T13:35:26.543 回答
5

我找到了对您遇到的问题的正确解释以及一些解决方案。

请参阅比较浮点值有多危险?

只是附带说明,请记住,某些值不能在 IEEE 754 浮点表示中精确表示。您使用 1.5 值的相同示例将按您预期的那样进行比较,因为 1.5 的完美表示没有任何数据丢失。但是 32 位和 64 位中的 1.1 实际上是不同的值,因为 IEEE 754 标准不能完美地表示 1.1。

http://www.binaryconvert.com

double a = 1.1 --> 0x3FF199999999999A

近似表示 = 1.10000000000000008881784197001

float  b = 1.1 --> 0x3f8ccccd

近似表示 = 1.10000002384185791015625

如您所见,这两个值是不同的。

此外,除非您在一些有限的内存类型环境中工作,否则使用浮点数毫无意义。只需使用双打,就可以避免头痛。

如果您不清楚为什么某些值无法准确表示,请参阅有关如何将小数转换为浮点的教程。

这是一个:http ://class.ece.iastate.edu/arun/CprE281_F05/ieee754/ie5.html

于 2013-06-27T12:33:46.140 回答
1

我认为直接在没有类型转换的情况下执行 afloat和 a之间的比较的代码会被破坏;double即使语言规范说float将被隐式转换,也有两种不同的方式可以明智地执行比较,并且两种方式都不足以真正证明“静默”默认行为是合理的(即编译时不产生警告的方式) . 如果想通过将两个操作数都评估为 来执行转换double,我建议添加显式类型转换以明确意图。但是,在大多数情况下,除了测试特定double->float转换是否可逆而不损失精度之外,我怀疑float值之间的比较可能更合适。

从根本上说,在比较浮点值XY任何类型时,应该将比较视为表明XY更大,或者数字是“无法区分的”。X应进行显示较大的比较,以表明应表示的数字Y可能小于X或接近X。一个说数字无法区分的比较就是这个意思。如果以这种方式看待事物,则通过强制转换执行的比较float可能不像使用 进行的比较那样“信息丰富” double,但不太可能产生完全错误的结果。相比之下,考虑:

double x, y;
float f = x;

如果比较fand y,可能感兴趣的是如何yxrounded to a float的值进行比较,但更可能的是,人们真正想知道的是,如果知道 的舍入值x,是否可以说什么关于x和之间的关系y。如果x是 0.1 和y0.2,f就会有足够的信息来说明是否x大于y;如果y是 0.100000001,则不会。在后一种情况下,如果两个操作数都强制转换为 double,则比较将错误地暗示x更大;如果它们都被转换为浮动,则比较会将它们报告为无法区分。请注意,将两个操作数转换为时的比较结果double可能是错误的,不仅当值在百万分之一以内时;它们可能相差数百个数量级,例如 x=1e40 和 y=1e300。比较fyas float,它们会比较难以区分;比较它们,double较小的值会错误地比较大。

于 2013-06-28T21:28:02.287 回答
0

舍入误差发生在 1.1 而不是 1.5 的原因是由于在浮点格式中准确表示像 0.1 这样的数字所需的位数。事实上,准确的表示是不可能的。

有关示例,请参见如何在浮点算术和小数中表示 0.1,尤其是@paxdiablo 的答案。

于 2013-06-27T12:35:01.050 回答