精华内容
下载资源
问答
  • 在深入了解浮点数的实现之前,先来看几个 Python 浮点数计算有意思的例子:0.1 == 0.10000000000000000000001IEEE 浮点数表示法这些看起来违反常识的“错误”并非 Python 的错,而是由浮点数的规则所决定的,即使放...

    浮点数用来存储计算机中的小数,与现实世界中的十进制小数不同的是,浮点数通过二进制的形式来表示一个小数。在深入了解浮点数的实现之前,先来看几个 Python 浮点数计算有意思的例子:

    0.1 == 0.10000000000000000000001

    IEEE 浮点数表示法

    这些看起来违反常识的“错误”并非 Python 的错,而是由浮点数的规则所决定的,即使放到其它语言中结果也是这样的。要理解计算机中浮点数的表示规则,先来看现实世界中十进制小数是如何表示的:

    1.234 = 1 + 1/10 + 2/100 + 3/1000

    可以用下面的公式来表示:

    tex_df1fd2d2a15a2d293bf23be9be0094e9.gif

    其中

    tex_d247f594c78d0d2be10fc6d82512cc4e.gif 是十进制中 0~9 的数字。而如果是一个二进制的小数:

    1.001 = 1 + 0/2 + 0/4 + 1/8

    可以用下面的公式来表示:

    tex_4e8a49b20452b31ea1aab09f57fc7f7d.gif

    其中

    tex_d247f594c78d0d2be10fc6d82512cc4e.gif 是二进制中的 0 或 1。Python 中的浮点数都是双精度的,也就说采用 64 位来表示一个小数,那这 64 位分别有多少用来表示整数部分和小数部分呢?根据 IEEE 标准,考虑到符号位,双精度表示法是这样分配的:

    tex_221d3e930326f53116674557aa8b8aff.gif

    也就是说用1位表示符号位,11位表示整数部分,52位表示小数部分。正如十进制中我们无法精确表示某些分数(如10/3),浮点数中通过 d1/2 + d2/4 + ... 的方式也会出现这种情况,比如上面的例子中,十进制中简单的 0.1 就无法在二进制中精确描述,而只能通过近似表示法表示出来:

    (3602879701896397, 36028797018963968)

    也就是说 0.1 是通过 3602879701896397/36028797018963968 来近似表示的,很明显这样近似的表示会导致许多差距很小的数字公用相同的近似表示数,例如:

    (0.10000000000000001).as_integer_ratio()

    (3602879701896397, 36028797018963968)

    在 Python 中所有这些可以用相同的近似数表示的数字统一采用最短有效数字来表示:

    print(0.10000000000000001)

    浮点数运算

    既然有些浮点数是通过近似值表示的,那么在计算过程中就很容易出现误差,就像最开始的第二个例子一样:

    a = .1 + .1 + .1

    b = .3

    print(a.as_integer_ratio())

    print(b.as_integer_ratio())

    print(a == b)

    (1351079888211149, 4503599627370496)

    (5404319552844595, 18014398509481984)

    False

    为了解决运算中的问题,IEEE 标准还指定了一个舍入规则(round),即 Python 中内置的 round 方法,我们可以通过舍入的方式取得两个数的近似值,来判断其近似值是否相等:

    round(a, 10) == round(b, 10)

    当然这种舍入的方式并不一定是可靠的,依赖于舍入的选择的位数,位数太大,就失去了 round 的作用,太小,就会引入别的错误:

    print(round(a, 17) == round(b, 17))

    print(round(0.1, 1) == round(0.111, 1))

    Python 中使用更精确的浮点数可以通过 decimal 和 fractions 两个模块,从名字上也能猜到,decimal 表示完整的小数,而 fractions 通过分数的形式表示小数:

    from decimal import Decimal

    a = Decimal(0.1)

    b = Decimal(0.1000000000000001)

    c = Decimal(0.10000000000000001)

    print(a)

    print(b)

    print(c)

    a == b == c

    0.1000000000000000055511151231257827021181583404541015625

    0.10000000000000010269562977782697998918592929840087890625

    0.1000000000000000055511151231257827021181583404541015625

    False

    from fractions import Fraction

    f1 = Fraction(1, 10) # 0.1

    print(float(f1))

    f3 = Fraction(3, 10) # 0.3

    print(float(f3))

    print(f1 + f1 + f1 == f3)

    总结

    浮点数这些奇特的特性让我们不得不在使用的时候格外注意,尤其是当有一定的精度要求的情况下。如果真的是对精度要求较高且需要频繁使用浮点数,建议使用更专业的 SciPy 科学计算包。

    打赏支持我写出更多好文章,谢谢!

    打赏作者

    打赏支持我写出更多好文章,谢谢!

    58883_0.jpg

    展开全文
  • Python 浮点数运算

    2016-05-12 04:31:00
    2019独角兽企业重金招聘Python工程师标准>>> ...

    浮点数用来存储计算机中的小数,与现实世界中的十进制小数不同的是,浮点数通过二进制的形式来表示一个小数。在深入了解浮点数的实现之前,先来看几个 Python 浮点数计算有意思的例子:

    0.1 == 0.10000000000000000000001
    
    True
    
    0.1+0.1+0.1 == 0.3
    
    False
    

    IEEE 浮点数表示法

    这些看起来违反常识的“错误”并非 Python 的错,而是由浮点数的规则所决定的,即使放到其它语言中结果也是这样的。要理解计算机中浮点数的表示规则,先来看现实世界中十进制小数是如何表示的:

    1.234 = 1 + 1/10 + 2/100 + 3/1000
    

    可以用下面的公式来表示:

    $$d = \sum_{i=-n}^m10^i*d_i$$

    其中 $d_i$ 是十进制中 0~9 的数字。而如果是一个二进制的小数:

    1.001 = 1 + 0/2 + 0/4 + 1/8
    

    可以用下面的公式来表示:

    $$d = \sum_{i=-n}^m2^i*d_i$$

    其中 $d_i$ 是二进制中的 0 或 1。Python 中的浮点数都是双精度的,也就说采用 64 位来表示一个小数,那这 64 位分别有多少用来表示整数部分和小数部分呢?根据 IEEE 标准,考虑到符号位,双精度表示法是这样分配的:

    $$d = s * \sum_{i=-52}^{11} 2^i*d_i$$

    也就是说用1位表示符号位,11位表示整数部分,52位表示小数部分。正如十进制中我们无法精确表示某些分数(如10/3),浮点数中通过 d1/2 + d2/4 + ... 的方式也会出现这种情况,比如上面的例子中,十进制中简单的 0.1 就无法在二进制中精确描述,而只能通过近似表示法表示出来:

    (0.1).as_integer_ratio()
    
    (3602879701896397, 36028797018963968)
    

    也就是说 0.1 是通过 3602879701896397/36028797018963968 来近似表示的,很明显这样近似的表示会导致许多差距很小的数字公用相同的近似表示数,例如:

    (0.10000000000000001).as_integer_ratio()
    
    (3602879701896397, 36028797018963968)
    

    在 Python 中所有这些可以用相同的近似数表示的数字统一采用最短有效数字来表示:

    print(0.10000000000000001)
    
    0.1
    

    浮点数运算

    既然有些浮点数是通过近似值表示的,那么在计算过程中就很容易出现误差,就像最开始的第二个例子一样:

    a = .1 + .1 + .1
    b = .3
    print(a.as_integer_ratio())
    print(b.as_integer_ratio())
    print(a == b)
    
    (1351079888211149, 4503599627370496)
    (5404319552844595, 18014398509481984)
    False
    

    为了解决运算中的问题,IEEE 标准还指定了一个舍入规则(round),即 Python 中内置的 round 方法,我们可以通过舍入的方式取得两个数的近似值,来判断其近似值是否相等:

    round(a, 10) == round(b, 10)
    
    True
    

    当然这种舍入的方式并不一定是可靠的,依赖于舍入的选择的位数,位数太大,就失去了 round 的作用,太小,就会引入别的错误:

    print(round(a, 17) == round(b, 17))
    print(round(0.1, 1) == round(0.111, 1))
    
    False
    True
    

    Python 中使用更精确的浮点数可以通过 decimalfractions 两个模块,从名字上也能猜到,decimal 表示完整的小数,而 fractions 通过分数的形式表示小数:

    from decimal import Decimal
    a = Decimal(0.1)
    b = Decimal(0.1000000000000001)
    c = Decimal(0.10000000000000001)
    print(a)
    print(b)
    print(c)
    
    a == b == c
    
    0.1000000000000000055511151231257827021181583404541015625
    0.10000000000000010269562977782697998918592929840087890625
    0.1000000000000000055511151231257827021181583404541015625
    
    
    
    
    
    False
    
    from fractions import Fraction
    f1 = Fraction(1, 10) # 0.1
    print(float(f1))
    f3 = Fraction(3, 10) # 0.3
    print(float(f3))
    
    print(f1 + f1 + f1 == f3)
    
    0.1
    0.3
    True
    

    总结

    浮点数这些奇特的特性让我们不得不在使用的时候格外注意,尤其是当有一定的精度要求的情况下。如果真的是对精度要求较高且需要频繁使用浮点数,建议使用更专业的 SciPy 科学计算包。


    pyhub

    转载于:https://my.oschina.net/rainyear/blog/673802

    展开全文
  • 计算机智能处理可数集合的运算,但是全体实数是不可数的,所以计算机只能用一些奇怪的方法来拟合他,于是就产生了浮点数。为什么说浮点数缺乏精确性?在开始本文之前,让我们先来谈谈浮点数为什么缺乏精确性的问题,...

    计算机智能处理可数集合的运算,但是全体实数是不可数的,所以计算机只能用一些奇怪的方法来拟合他,于是就产生了浮点数。

    为什么说浮点数缺乏精确性?

    在开始本文之前,让我们先来谈谈浮点数为什么缺乏精确性的问题,其实这不是Python的问题,而是实数的无限精度跟计算机的有限内存之间的矛盾。

    举个例子,假如说我只能使用整数(即只精确到个位,计算机内的浮点数也只有有限精度,以C语言中的双精度浮点数double为例,精度为52个二进制位),要表示任意实数(无限精度)的时候我就只能通过舍入(rounding)来近似表示。

    比如1.2我会表示成1,2.4表示成2,3.6表示成4.

    所以呢?

    在算1.2 - 1.2的时候,由于计算机表示的问题,我算的实际上是1 - 1,结果是0,碰巧蒙对了;

    在算1.2 + 1.2 - 2.4的时候,由于计算机表示的问题,我算的实际上是1 + 1 - 2,结果是0,再次蒙对了;

    但是在算1.2 + 1.2 + 1.2 - 3.6的时候,由于计算机表示的问题,我算的实际上是1 + 1 + 1 - 4,结果是-1,运气没那么好啦!

    这里的1.2, 2.4, 3.6就相当于你问题里的0.1, 0.2和0.3,1, 2, 4则是真正在计算机内部进行运算的数值,我说清楚了吗?

    其他请看IEEE 754浮点数标准,比如CSAPP第二章啥的(虽然估计你没兴趣看)。

    另:不仅仅是浮点数的在计算机内部的表示有误差,运算本身也可能会有误差。比如整数2可以在计算机内准确表示,但是要算根号2就有误差了;再比如两个浮点数相除,本来两个数都是精确表示的,但除的结果精度却超出了计算机内实数的表示范围,然后就有误差了。

    好了,下面话不多说了,开始本文的正文:

    起步

    浮点数的一个普遍的问题是它们不能精确的表示十进制数。

    >>> a = 4.2

    >>> b = 2.1

    >>> a + b

    6.300000000000001

    >>> (a + b) == 6.3

    False

    >>>

    这是由于底层 CPU 和IEEE 754标准通过自己的浮点单位去执行算术时的特征。看似有穷的小数,在计算机的二进制表示里却是无穷的。

    一般情况下,这一点点的小误差是允许存在的。如果不能容忍这种误差(比如金融领域),那么就要考虑用一些途径来解决这个问题了。

    Decimal

    使用这个模块不会出现任何小误差。

    >>> from decimal import Decimal

    >>> a = Decimal('4.2')

    >>> b = Decimal('2.1')

    >>> a + b

    Decimal('6.3')

    >>> print(a + b)

    6.3

    >>> (a + b) == Decimal('6.3')

    True

    尽管代码看起来比较奇怪,使用字符串来表示数字,但是 Decimal 支持所有常用的数学运算。decimal模块允许你控制计算的每一方面,包括数字位数和四舍五入。在这样做之前,需要创建一个临时上下文环境来改变这种设定:

    >>> from decimal import Decimal, localcontext

    >>> a = Decimal('1.3')

    >>> b = Decimal('1.7')

    >>> print(a / b)

    0.7647058823529411764705882353

    >>> with localcontext() as ctx:

    ... ctx.prec = 3

    ... print(a / b)

    ...

    0.765

    >>> with localcontext() as ctx:

    ... ctx.prec = 50

    ... print(a / b)

    ...

    0.76470588235294117647058823529411764705882352941176

    >>>

    由于 Decimal 的高精度数字自然也就用字符串来做展示和中转。

    总结

    总的来说,当涉及金融领域时,哪怕是一点小小的误差在计算过程中都是不允许的。因此 decimal 模块为解决这类问题提供了方法。

    展开全文
  • python浮点数运算问题

    2020-07-22 19:51:50
    python中对于一些浮点数运算结果,往往出现一些意想不到的结果,该博客主要讲解导致这样的原因以及解决办法。

    python浮点数运算问题

    在python中对于一些浮点数的运算结果,往往出现一些意想不到的结果。

    原因

    在python中:

    一个十进制数 >>>以二进制形式(近似值)存储到计算机>>>读取计算机中该二进制近似值的十进制近似值

    由于一些十进制的浮点数,转换为二进制值存储到计算机时,会出现无限循环的二进制值的情况,而计算机的位数是有限的,因此在计算机再次读取该二进制数据转为十进制数据的时候,最终导致结果为近似值。

    例如

    print('9.2 - 2.2 =',9.2 - 2.2)
    

    结果:
    9.2 - 2.2 = 6.999999999999999

    解决办法:

    1.对于浮点数大小比较问题,可以调用math来进行比较
    例如:

    import math
    math.isclose(a,b)
    

    来比较浮点数a和b是否大小相同

    2.对于浮点数的计算,可以通过调用decimal模块,将浮点数先转换为字符串,再进行运算。
    例如:

    from decimal import Decimal
    a = Decimal('9.2')
    b = Decimal('2.2')
    print('9.2 - 2.2 =',a-b)
    

    结果:
    9.2 - 2.2 = 7.0

    展开全文
  • python浮点数运算误差

    2020-12-24 16:30:28
    我会陆续更新python基础知识,关注我不迷路。
  • Python 浮点数运算错误问题

    千次阅读 2018-05-06 21:50:10
    浮点数运算错误溢出[in]: a = 1.1 b = 2.2 a + b[out]: 3.3000000000000003解决方法用Python提供的decimal模块,将浮点数先转换为字符串,再进行运算from decimal import Decimal a = Decimal('1.1') b = ...
  • 解决python浮点数运算精度有误差的问题,之所以不准确,是因为我们人用十进制而机器用二进制来回转换导致的。(许多高级语言都有类似的问题)用math库的一些方法也没用。 我们可以借助decimal标准库来解决。主要...
  • Python浮点数运算时 数据精度的处理

    千次阅读 2020-02-23 17:21:04
    浮点数 Python浮点数 运算的问题: 官方文档 不幸的是,大多数的十进制小数都不能精确地表示为二进制小数。这导致在大多数情况下,你输入的十进制浮点数都只能近似地以二进制浮点数形式储存在计算机中。 看个...
  • python浮点数运算,为什么0.1+0.2!=0.3?

    千次阅读 2020-03-20 11:04:13
    这是因为 在python浮点数运算***存在不确定尾数***的关系。 ------round(x,d):对x四舍五入,d是小数截取位数 ------不确定尾数一般发生在10的-16左右,round()十分有效 举例: ...
  • Decimal.from_float(0.1)

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,250
精华内容 14,500
关键字:

python浮点数运算

python 订阅