浮点比较中的问题

时间:2010-10-18 19:40:53

标签: c floating-point floating-point-conversion

void main()
{
    float f = 0.98;
    if(f <= 0.98)
        printf("hi");
    else
        printf("hello");
    getch();
}

我在这里遇到这个问题。使用f的不同浮点值我得到不同的结果。 为什么会这样?

2 个答案:

答案 0 :(得分:21)

f使用float精度,但默认情况下0.98的精度为double,因此使用f <= 0.98精度比较语句double

因此f在比较中转换为double,但可能会使结果略大于0.98。

使用

if(f <= 0.98f)

或使用double代替f


详细说明......假设floatIEEE single-precisiondoubleIEEE double-precision

这些浮点数以base-2表示形式存储。在base-2中,这个数字需要无限精度来表示,因为它是重复的小数:

0.98 = 0.1111101011100001010001111010111000010100011110101110000101000...

float只能存储24位有效数字,即

       0.111110101110000101000111_101...
                                 ^ round off here
   =   0.111110101110000101001000

   =   16441672 / 2^24

   =   0.98000001907...

double可以存储53位有意义的数字,所以

       0.11111010111000010100011110101110000101000111101011100_00101000...
                                                              ^ round off here
   =   0.11111010111000010100011110101110000101000111101011100

   =   8827055269646172 / 2^53

   =   0.97999999999999998224...

因此,float中的0.98会稍微变大,而double会变小。

答案 1 :(得分:3)

这是因为浮点值不是数字的精确表示。所有十个基数都需要在计算机上表示为基数2。在这种转换中,精度会丢失。

http://en.wikipedia.org/wiki/Floating_point

了解详情

一个例子(在我的VB6中遇到这个问题)

要将数字1.1转换为单精度浮点数,我们需要将其转换为二进制数。需要创建32位。

位1是符号位(是负[1]还是位置[0]) 位2-9用于指数值 第10-32位用于尾数(a.k.a。有效数,基本上是科学记数系数)

因此,对于1.1,单个浮点值存储如下(这是截断值,编译器可能会在幕后舍入最低有效位,但我所做的只是截断它,这稍微不准确但不是更改此示例的结果):

s --exp--- -------mantissa--------
0 01111111 00011001100110011001100

如果你注意到尾数中有重复模式0011.二进制的1/10就像十进制的1/3。它会永远持续下去。因此,要从32位单精度浮点值中检索值,我们必须首先将指数和尾数转换为十进制数,以便我们可以使用它们。

sign = 0 =正数

指数:01111111 = 127

尾数:00011001100110011001100 = 838860

使用尾数我们需要将其转换为十进制值。原因是在二进制数之前存在隐含的整数(即1.00011001100110011001100)。隐含数字是因为尾数表示要在科学计数法中使用的标准化值:1.0001100110011 .... * 2 ^(x-127)。

要从838860中取出十进制值,我们只需除以2 ^ -23,因为尾数中有23位。这给了我们0.099999904632568359375。将隐含的1添加到尾数给出1.099999904632568359375。指数为127,但公式需要2 ^(x-127)。

所以这是数学:

(1 + 099999904632568359375)* 2 ^(127-127)

1.099999904632568359375 * 1 = 1.099999904632568359375

正如您所看到的,1.1并未真正存储在单个浮点值1.1中。