python系列教程65
原创
©著作权归作者所有:来自51CTO博客作者人工智能AI技术的原创作品,请联系作者获取转载授权,否则将追究法律责任
声明:在人工智能技术教学期间,不少学生向我提一些python相关的问题,所以为了让同学们掌握更多扩展知识更好地理解AI技术,我让助理负责分享这套python系列教程,希望能帮到大家!由于这套python教程不是由我所写,所以不如我的AI技术教学风趣幽默,学起来比较枯燥;但它的知识点还是讲到位的了,也值得阅读!PS:看不懂本篇文章的同学请先看前面的文章,循序渐进每天学一点就不会觉得难了!
Python 2.6和Python 3.0引入了一种新的数字类型——分数,它实现了一个有理数对象。它明确地保留一个分子和一个分母,从而避免了浮点数学的某些不精确性和局限性。
分数是前一篇文章所介绍的已有的小数固定精度类型的“近亲”,它们都可以通过固定小数位数和指定舍入或截断策略来控制数值精度。分数以类似于小数的方式使用,它也存在于模块中;导入其构造函数并传递一个分子和一个分母就可以产生一个分数。下面的交互式例子展示了如何做到这一点:
>>> from fractions import Fraction
>>> x = Fraction(1,3) # Numerator,denominator
>>> y = Fraction(4,6) # Simplified to 2,3 by gcd
>>> x
Fraction(1,3)
>>> y
Fraction(2,3)
>>> print(y)
2/3
一旦创建了分数,它可以像平常一样用于数学表达式中:
>>> x + y
Fraction(1,1)
>>> x - y # Results are exact: numerator,denominator
Fraction(-1,3)
>>> x * y
Fraction(2,9)
分数对象也可以从浮点数字符串来创建,这和小数很相似:
>>> Fraction('.25')
Fraction(1,4)
>>> Fraction('1.25')
Fraction(5,4)
>>>
>>> Fraction('.25') + Fraction('1.25')
Fraction(3,2)
对于那些用内存中给定的有限位数无法精确表示的值,浮点数的局限尤为明显。分数和小数都提供了得到精确结果的方式,虽然要付出一些速度的代价。例如,在下面的例子中,浮点数并没有准确地给出期望的0的答案,但其他的两种类型都做到了:
>>> 0.1 + 0.1 + 0.1 - 0.3 # This should be zero (close,but not exact)
5.5511151231257827e-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 # Use 3.0 in Python 2.6 for true "/"
0.33333333333333331
>>> Fraction(1,3) # Numeric accuracy
Fraction(1,3)
>>> import decimal
>>> decimal.getcontext().prec = 2
>>> decimal.Decimal(1) / decimal.Decimal(3)
Decimal('0.33')
实际上,分数保持精确性,并且自动简化结果。继续前面的交互例子:
>>> (1 / 3) + (6 / 12) # Use ".0" in Python 2.6 for true "/"
0.83333333333333326
>>> Fraction(6,12) # Automatically simplified
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.1000000737100011e-07
>>> Fraction(1000,1234567890)
Fraction(100,123456789)
分数与浮点数之间是可以互相转换的:
>>> (2.5).as_integer_ratio() # float object method
(5,2)
>>> f = 2.5
>>> z = Fraction(*f.as_integer_ratio()) # Convert float -> fraction: two args
>>> z # Same as Fraction(5,2)
Fraction(5,2)
>>> x # x from prior interaction
Fraction(1,3)
>>> x + z
Fraction(17,6) # 5/2 + 1/3 = 15/6 + 2/6
>>> float(x) # Convert fraction -> float
0.33333333333333331
>>> float(z)
2.5
>>> float(x + z)
2.8333333333333335
>>> 17 / 6
2.8333333333333335
>>> Fraction.from_float(1.75) # Convert float -> fraction: other way
Fraction(7,4)
>>> Fraction(*(1.75).as_integer_ratio())
Fraction(7,4)
表达式中也允许某些类型的混合,尽管Fraction有时必须手动地传递以确保精度:
>>> x
Fraction(1,3)
>>> x + 2 # Fraction + int -> Fraction
Fraction(7,3)
>>> x + 2.0 # Fraction + float -> float
2.3333333333333335
>>> x + (1./3) # Fraction + float -> float
0.66666666666666663
>>> x + (4./3)
1.6666666666666665
>>> x + Fraction(4,3) # Fraction + Fraction -> Fraction
Fraction(5,3)
警告:尽管可以把浮点数转换为分数,但在某些情况下,这么做的时候会有不可避免的精度损失,因为这个数字在浮点形式下是不精确的。
我的微信公众号是“人工智能知识分享”
