即使是最基本的数学运算有时也会产生错误的结果。这是由于存储某些数字的精确值存在限制造成的。您可以通过使用Python中的decimal
模块来克服这些限制。同样,我们在上一个教程中学到的math
和cmath
模块都不能帮助我们进行基于分数的算术运算。但是,Python中的fractions
模块恰好可以做到这一点。
本教程将介绍这两个模块以及它们提供的不同函数。
from decimal import Decimal Decimal(121) # 返回 Decimal('121') Decimal(0.05) # 返回 Decimal('0.05000000000000000277555756') Decimal('0.05') # 返回 Decimal('0.05') Decimal((0, (8, 3, 2, 4), -3)) # 返回 Decimal('8.324') Decimal((1, (8, 3, 2, 4), -1)) # 返回 Decimal('-832.4')
如您所见,getcontext()
函数的值决定了计算的精度、舍入规则和异常引发行为。
您可以使用setcontext()
函数获取和设置计算的当前上下文。使用with
语句可以临时更改计算的上下文。
模块中有三个内置上下文可用于计算:ROUND_HALF_UP
、ROUND_HALF_EVEN
和ROUND_HALF_EVEN
作为其舍入算法。这些上下文之间的另一个区别是异常引发行为。DefaultContext
不会引发与数值溢出、无效操作和除以零相关的异常。BasicContext
启用了几乎所有异常,非常适合调试,而DefaultContext
用作计算的默认上下文。
以下是如何使用不同的上下文来获取简单除法的不同结果的示例:
import decimal from decimal import ROUND_DOWN, ROUND_UP, Decimal as D dec_a = D('0.153') dec_b = D('0.231') zero = D('0') print("无上下文(使用默认值): ", dec_a/dec_b) # 无上下文(使用默认值): 0.6623376623376623376623376623 decimal.setcontext(decimal.BasicContext) print("基本上下文: ", dec_a/dec_b) # 基本上下文: 0.662337662 decimal.setcontext(decimal.ExtendedContext) print("扩展上下文: ", dec_a/dec_b) # 扩展上下文: 0.662337662 print("扩展上下文: ", dec_b/zero) # 扩展上下文: Infinity decimal.setcontext(decimal.DefaultContext) print("默认上下文: ", dec_a/dec_b) # 默认上下文: 0.6623376623376623376623376623 with decimal.localcontext() as l_ctx: l_ctx.prec = 5 l_ctx.rounding = ROUND_UP print("局部上下文: ", dec_a/dec_b) # 局部上下文: 0.66234
除了注意到不同上下文的精度和舍入算法的差异外,您可能还观察到,在ExtendedContext
下,0 的除法结果为Infinity
。
decimal
模块中的许多函数也接受上下文对象作为参数来执行其计算。这样,您可以避免不断设置计算的上下文或精度值。
import decimal from decimal import Decimal as D print(D('22').sqrt(decimal.BasicContext)) # 4.69041576 print(D('22').sqrt(decimal.ExtendedContext)) # 4.69041576 print(D('22').sqrt(decimal.DefaultContext)) # 4.690415759823429554565630114 with decimal.localcontext() as l_ctx: l_ctx.prec = 5 print(D('22').sqrt(l_ctx)) # 4.6904
有时,您可能会遇到需要对分数执行各种运算或最终结果需要是一个分数的情况。fractions
模块在这种情况下可以提供很大的帮助。
fractions
模块允许您从数字、浮点数、十进制数甚至字符串创建Fraction
实例。与decimal
模块一样,当从浮点数创建分数时,此模块也存在一些问题。以下是一些示例:
from fractions import Fraction from decimal import Decimal Fraction(11, 35) # 返回 Fraction(11, 35) Fraction(10, 18) # 返回 Fraction(5, 9) Fraction('8/25') # 返回 Fraction(8, 25) Fraction(1.13) # 返回 Fraction(1272266894732165, 1125899906842624) Fraction('1.13') # 返回 Fraction(113, 100) Fraction(Decimal('1.13')) # 返回 Fraction(113, 100)
您还可以像普通数字一样对分数执行简单的数学运算,如加法和减法。
from decimal import Decimal Decimal(121) # 返回 Decimal('121') Decimal(0.05) # 返回 Decimal('0.05000000000000000277555756') Decimal('0.05') # 返回 Decimal('0.05') Decimal((0, (8, 3, 2, 4), -3)) # 返回 Decimal('8.324') Decimal((1, (8, 3, 2, 4), -1)) # 返回 Decimal('-832.4')
该模块还有一些重要的方法,例如limit_denominator(max_denominator)
,它将找到并返回一个最接近给定分数的值的分数,其分母最多为max_denominator
。您还可以使用numerator
属性返回给定分数的分子(以最低项表示),使用denominator
属性返回分母。
import decimal from decimal import ROUND_DOWN, ROUND_UP, Decimal as D dec_a = D('0.153') dec_b = D('0.231') zero = D('0') print("无上下文(使用默认值): ", dec_a/dec_b) # 无上下文(使用默认值): 0.6623376623376623376623376623 decimal.setcontext(decimal.BasicContext) print("基本上下文: ", dec_a/dec_b) # 基本上下文: 0.662337662 decimal.setcontext(decimal.ExtendedContext) print("扩展上下文: ", dec_a/dec_b) # 扩展上下文: 0.662337662 print("扩展上下文: ", dec_b/zero) # 扩展上下文: Infinity decimal.setcontext(decimal.DefaultContext) print("默认上下文: ", dec_a/dec_b) # 默认上下文: 0.6623376623376623376623376623 with decimal.localcontext() as l_ctx: l_ctx.prec = 5 l_ctx.rounding = ROUND_UP print("局部上下文: ", dec_a/dec_b) # 局部上下文: 0.66234
您还可以将此模块与math
模块中的各种函数一起使用来执行基于分数的计算。
import decimal from decimal import Decimal as D print(D('22').sqrt(decimal.BasicContext)) # 4.69041576 print(D('22').sqrt(decimal.ExtendedContext)) # 4.69041576 print(D('22').sqrt(decimal.DefaultContext)) # 4.690415759823429554565630114 with decimal.localcontext() as l_ctx: l_ctx.prec = 5 print(D('22').sqrt(l_ctx)) # 4.6904
这两个模块应该足以帮助您对十进制数和分数执行常见运算。如最后一节所示,您可以将这些模块与math
模块一起使用,以您希望的格式计算各种数学函数的值。
在本系列的下一个教程中,您将学习Python中的random
模块。
以上是Python中的数学模块:十进制和分数的详细内容。更多信息请关注PHP中文网其他相关文章!