双重和浮动比较

时间:2013-06-27 12:26:41

标签: c++ floating-point double floating-point-precision

根据this post,在比较float和double时,float应该被视为double。 以下程序似乎没有遵循此声明。这种行为看起来非常不可预测。 这是我的计划:

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 个答案:

答案 0 :(得分:10)

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

在此比较中,f的值会提升为double类型。您所看到的问题不是在比较中,而是在初始化中。 1.1无法完全表示为浮点值,因此fd中存储的值是可以表示的最接近的值。但floatdouble的大小不同,因此具有不同数量的有效位。当f中的值被提升为double时,无法获取存储该值时丢失的额外位,因此最终会在额外位中使用全零。那些零位与d中的位不匹配,因此比较为假。与1.5进行比较成功的原因是1.5 可以完全表示为floatdouble;它的低位有一堆零,所以当促销添加零时,结果与double表示相同。

答案 1 :(得分:5)

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

请参阅How dangerous is it to compare floating point values?

请注意,请记住,某些值无法在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

答案 2 :(得分:1)

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

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

double x, y;
float f = x;

如果比较fy,那么感兴趣的是y与舍入浮点数x的值的比较,但它是更有可能的是,真正想知道的是,是否知道x的舍入值,是否可以对xy之间的关系发表任何意见。如果x为0.1且y为0.2,则f会提供足够的信息来说明x是否大于y;如果y是0.100000001,则不会。在后一种情况下,如果两个操作数都被转换为double,则比较将错误地暗示x更大;如果它们都被转换为浮动,则比较将报告它们无法区分。请注意,将两个操作数转换为double时的比较结果可能不仅在值在百万分之一范围内时也是错误的;它们可能会偏离数百个数量级,例如x = 1e40且y = 1e300。将fy作为float进行比较,它们会比较难以区分;将它们比作double,较小的值会错误地比较较大。

答案 3 :(得分:0)

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

请参阅How To Represent 0.1 In Floating Point Arithmetic And Decimal以获取示例,尤其是@paxdiablo的答案。