搜索

首页  >  问答  >  正文

c/c++ 比较两个浮点数相等

PHP中文网PHP中文网2807 天前722

全部回复(2)我来回复

  • PHP中文网

    PHP中文网2017-04-17 15:10:48

    首先,两个 if 是一样的。浮点数和整数比较时,整数被转为浮点数。
    然后,i 为什么不等于 10.0?因为它只会等于这些值:

    >>> def gen():
    ...   i = 0
    ...   while i < 10:
    ...     i += 0.1
    ...     yield i
    ...
    >>> L = list(gen())
    >>> L
    [0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6, 0.7, 0.7999999999999999, 0.8999999999999999, 0.9999999999999999, 1.0999999999999999, 1.2, 1.3, 1.4000000000000001, 1.5000000000000002, 1.6000000000000003, 1.7000000000000004, 1.8000000000000005, 1.9000000000000006, 2.0000000000000004, 2.1000000000000005, 2.2000000000000006, 2.3000000000000007, 2.400000000000001, 2.500000000000001, 2.600000000000001, 2.700000000000001, 2.800000000000001, 2.9000000000000012, 3.0000000000000013, 3.1000000000000014, 3.2000000000000015, 3.3000000000000016, 3.4000000000000017, 3.5000000000000018, 3.600000000000002, 3.700000000000002, 3.800000000000002, 3.900000000000002, 4.000000000000002, 4.100000000000001, 4.200000000000001, 4.300000000000001, 4.4, 4.5, 4.6, 4.699999999999999, 4.799999999999999, 4.899999999999999, 4.999999999999998, 5.099999999999998, 5.1999999999999975, 5.299999999999997, 5.399999999999997, 5.4999999999999964, 5.599999999999996, 5.699999999999996, 5.799999999999995, 5.899999999999995, 5.999999999999995, 6.099999999999994, 6.199999999999994, 6.299999999999994, 6.399999999999993, 6.499999999999993, 6.5999999999999925, 6.699999999999992, 6.799999999999992, 6.8999999999999915, 6.999999999999991, 7.099999999999991, 7.19999999999999, 7.29999999999999, 7.39999999999999, 7.499999999999989, 7.599999999999989, 7.699999999999989, 7.799999999999988, 7.899999999999988, 7.999999999999988, 8.099999999999987, 8.199999999999987, 8.299999999999986, 8.399999999999986, 8.499999999999986, 8.599999999999985, 8.699999999999985, 8.799999999999985, 8.899999999999984, 8.999999999999984, 9.099999999999984, 9.199999999999983, 9.299999999999983, 9.399999999999983, 9.499999999999982, 9.599999999999982, 9.699999999999982, 9.799999999999981, 9.89999999999998, 9.99999999999998, 10.09999999999998]

    你可以看到,浮点数十进制转二进制有误差。100 次误差积累之后,i 只会等于 9.99999999999998。(我使用的是 Python 3.6,浮点数的十进制表示会采用等价表示法中最短的。它也是采用与 C 语言相同的内部表示。)

    浮点数在计算机中是以二进制形式表示和运算的(通常使用 IEEE 754 标准),而 0.1 不能精确地用二进制来表示(是循环小数;只有分母只包含因子 2 的小数,使用二进制表示时才不会循环)。这样一来就会有误差。误差积累之下,它会就偏离十进制越来越远。

    如果你需要比较相等性,可以与指定的数求差,如果差值小于特定值(比如 Python 里有 math.isclose 函数),就认为相等。

    如果你需要精确值(比如做金融计算,一分钱也不能少的那种),你可以使用所谓的「十进制数」来运算(decimal,Python 和 Ruby 都支持的。也可以使用 mpdecimal 库),或者指定精度(比如使用 mpfr 库),或者使用定点数。

    回复
    0
  • 高洛峰

    高洛峰2017-04-17 15:10:48

    关于 强数据类型的语言来说, 对于double float这样的有小数点的数据,进行比较的时候, 一般不是使用== 进行比较的.

    而是 比较两个数相减的绝对值, 如果这个绝对值小于一个很小的数值, 那么我们就认为这两个浮点数相等.

    如下代码:

    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    int main(int argc, char **argv)
    {
        for(double i=0; i!=10; i += 0.1)
        {
            if( fabs( i - 10.0 ) < 0.00000001 ) ///< fabs: 获得double类型的绝对值
            {
                cout << "i equal 10" << '\n';
                break;
            }
    
            cout << i << '\n';
    
            if( i > 20 )
            {
                break;
            }
        }
        return 0;
    }

    之所以会这样,是和计算机本身采用01二进制表示数据有关.

    基本可以这样理解:因为计算机内部浮点数的保存格式,很多在内存中保存的浮点数只是以尽可能接近的形式保存

    感兴趣的话, 可以进一步深入了解.

    博客园文章

    回复
    0
  • 取消回复