其他的数字类型——分数类型——在分数和小数中的数字精度

未匹配的标注

注意这和浮点类型(它被浮点硬件的潜在限制所约束)的数学不同。为了比较,下面是使用浮点对象运行的同样操作和对它们受限精度的注释——在最近版本的Python中可能会显示比之前更少的数位,但它们在内存中仍然不是准确的值:

>>> a = 1 / 3.0 # 只和浮点硬件一样准确
>>> b = 4 / 6.0 # 经过许多计算会丢失精度
>>> a
0.3333333333333333
>>> b
0.6666666666666666
>>> a + b
1.0
>>> a - b
-0.3333333333333333
>>> a * b
0.2222222222222222

这个浮点限制对那些因为内存中比特位受限而无法精确表示的值特别明显。分数小数都提供了获得准确结果的方法,虽然是以一些速度和代码冗余为代价的。比如,在下面例子中(从之前章节中重复的),浮点数不能准确给出期待的答案0,但其他两个类型都可以:

>>> 0.1 + 0.1 + 0.1 - 0.3 # 这应该是0(接近了,但不准确)
5.551115123125783e-17
>>> from fractions import Fraction
>>> Fraction(1, 10) + Fraction(1, 10) + Fraction(1, 10) - Fraction(3,
10)
Fraction(0, 1)
>>> from decimal import Decimal
>>> Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')
Decimal('0.0')

而且,有时,分数和小数都允许比浮点数更直观和准确的结果,以不同的方式——通过使用分数表示和限制精度:

>>> 1 / 3 # 在Python 2系列中使用一个".0"来表示真正的除法
0.3333333333333333
>>> Fraction(1, 3) # 数字精度,两种方法
Fraction(1, 3)
>>> import decimal
>>> decimal.getcontext().prec = 2
>>> Decimal(1) / Decimal(3)
Decimal('0.33')

事实上,分数保留了精度并自动简化结果。继续之前的交互:

>>> (1 / 3) + (6 / 12) # 在Python 2系列中使用一个".0"来表示真正的除法
0.8333333333333333
>>> Fraction(6, 12) # 自动简化
Fraction(1, 2)
>>> Fraction(1, 3) + Fraction(6, 12)
Fraction(5, 6)
>>> decimal.Decimal(str(1/3)) + decimal.Decimal(str(6/12))
Decimal('0.83')
>>> 1000.0 / 1234567890
8.100000073710001e-07
>>> Fraction(1000, 1234567890) # 要简单得多!
Fraction(100, 123456789)

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~