【问题标题】:Unexpected floating point comparisons [duplicate]意外的浮点比较[重复]
【发布时间】:2026-02-05 12:05:01
【问题描述】:

考虑以下代码:

#include<stdio.h>
#define k 0.7
#define p 0.5
int main()
{
    float a=k,b=p;
    double aa=k;
    if(a<k)
    {
         if(b<p) printf("2 is right");    
         else      printf("1 is right");
    }
    else printf("0 is right");
    printf("\n");
    if(a>k)
    {
         if(b<p) printf("2 is right");    
         else      printf("1 is right");
    }
    else printf("0 is right");
    return 0;
}

将此视为this 问题的第二部分,这里的理解是浮点常量(表示为数字常量时的双精度值)在转换为相应的浮点值时丢失了。异常值为 X.5 和 X.0。但我观察到以下结果:

Input           Output
K=0.1 to 0.4        0 is right
                    1 is right

K=0.5               0 is right
                    1 is right

K=0.6               0 is right
                    1 is right

K=0.7               1 is right
                    0 is right

K=0.8               0 is right
                    1 is right

K=0.9               1 is right
                    0 is right

K=8.4               1 is right
                    0 is right

为什么会有这种奇怪的行为?为什么只有少数浮点值显示此属性?难道我们不能假设float 精度值总是小于double 精度值吗?我们如何解释这种行为?

【问题讨论】:

  • a 在您的示例中始终等于 k。输入在哪里发挥作用?
  • 有时将double 转换为float 会产生较小的值,有时会产生较大的值,有时值相同。有什么问题?
  • @0A0D 真的吗??那么在所有情况下,我都应该有0 is right 作为答案。在你投反对票之前好好看看
  • @sasidhar: float a = k;... 在if (a&lt;k) 之前a 的变化在哪里?我投了反对票,因为这是一个糟糕的问题。
  • @sasidhar 取决于数字的二进制扩展。从double 转换为float 将精度从53 位降低到24 位。如果第 25 位为 0,则截断(向零舍入),如果为 1,则从零舍入,除非第 25 位是最后 1 位,否则将舍入以使第 24 位是 0。

标签: c floating-point precision floating-accuracy


【解决方案1】:

我们不能假设float 精度值总是小于double 精度值吗??

并非如此,它们可能都具有相同的精度。可以假设double的范围和精度不小于float

但是,出于所有实际目的,double 具有 53 位精度,float 具有 24 位精度是一个有利可图的赌注。double 具有 11 位指数,float 8 位。

因此,不管外来架构,float 的精度和范围都比double 小,每个float 值都可以表示为double,但反之则不然。所以从float 转换为double 是保值的,但从double 转换为float 会改变所有需要超过24 位精度的值。

通常通过以下方式将 double 值的有效位四舍五入为 24 位精度来执行转换(对于 float 范围内的值):

  • 如果有效数字的第 25 个最高有效位为 0,则有效数字被截断(值向零舍入)
  • 如果第 25 个最高有效位为 1,并且并非所有较低有效位都为 0,则从零开始舍入该值(有效位被截断,然后是最低有效位的值位被添加)
  • 1234563

您无法通过查看小数扩展来预测将double 转换为float 是否会增加或减少值,除非在少数情况下您可以看到该值将保持不变。重要的是二进制扩展。

【讨论】: