鱼C论坛

 找回密码
 立即注册
查看: 51739|回复: 194

[速查宝典] decimal -- 十进制定点和浮点运算

  [复制链接]
发表于 2019-9-18 07:47:12 | 显示全部楼层 |阅读模式
购买主题 已有 12 人购买  本主题需向作者支付 10 鱼币 才能浏览
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-9-21 01:00:27 | 显示全部楼层
我要好好看文档
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 0 反对 1

使用道具 举报

发表于 2019-9-21 14:13:53 | 显示全部楼层
很棒鸭
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-10-9 13:28:29 | 显示全部楼层
我要好好看文档
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-10-15 14:16:04 | 显示全部楼层
我要好好看文档。
看不懂啊。。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

发表于 2019-12-24 00:49:15 From FishC Mobile | 显示全部楼层
看不了怎么
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 1

使用道具 举报

发表于 2020-1-2 16:11:29 | 显示全部楼层
我要好好看文档
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-25 21:14:53 From FishC Mobile | 显示全部楼层
我要好好看文档
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-28 17:03:47 | 显示全部楼层
我要好好看文档
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-30 16:33:43 From FishC Mobile | 显示全部楼层
我要好好看文档
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-31 00:44:09 | 显示全部楼层
该decimal模块支持快速正确舍入的十进制浮点运算。与float数据类型相比,它具有一些优点 :

十进制“基于一个浮点模型,该浮点模型是为人而设计的,并且必然具有最重要的指导原则–计算机必须提供一种与人们在学校学习的算法相同的算法。” –摘自十进制算术规范。

小数可以精确表示。相反,数字喜欢 1.1和2.2没有在二进制浮点数中具有精确的表示形式。最终用户通常不会期望像二进制浮点那样显示。1.1 + 2.23.3000000000000003

准确性会转入算术运算。在十进制浮点数中,正好等于零。在二进制浮点中,结果为。当接近零时,差异会阻止可靠的相等性测试,并且差异会累积。因此,在具有严格相等不变性的会计应用程序中,首选十进制。0.1 + 0.1 + 0.1 - 0.35.5511151231257827e-017

小数模块具有显著场所的概念,这样是。尾随零将保留以指示重要性。这是货币应用程序的惯用表示。对于乘法,“教科书”方法使用被乘数中的所有数字。举例来说,给人的同时给人。1.30 + 1.202.501.3 * 1.21.561.30 * 1.201.5600

与基于硬件的二进制浮点数不同,十进制模块具有用户可更改的精度(默认为28位),该精度可以与给定问题所需的精度一样大:

from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
Decimal('0.142857')
getcontext().prec = 28
Decimal(1) / Decimal(7)
Decimal('0.1428571428571428571428571429')
二进制和十进制浮点数都是根据已发布的标准实现的。内置的float类型仅公开其功能的适度部分,而十进制模块则公开标准的所有必需部分。在需要时,程序员可以完全控制舍入和信号处理。这包括通过使用异常来阻止任何不精确操作来强制执行精确算术的选项。

十进制模块被设计为支持“在不存在偏见的情况下,精确的无舍入十进制算术(有时称为定点算术)和舍入浮点算术。” –摘自十进制算术规范。

模块设计围绕三个概念:十进制数,算术上下文和信号。

十进制数字是不可变的。它具有一个符号,系数数字和一个指数。为了保留重要性,系数数字不会截断尾随零。小数也包括特殊值,如 Infinity,-Infinity和NaN。该标准还区分-0的+0。

算术的上下文是一个环境,用于指定精度,舍入规则,指数限制,指示运算结果的标志以及确定信号是否被视为异常的陷阱启用器。舍入选项包括ROUND_CEILING,ROUND_DOWN, ROUND_FLOOR,ROUND_HALF_DOWN,ROUND_HALF_EVEN, ROUND_HALF_UP,ROUND_UP,和ROUND_05UP。

信号是在计算过程中出现的一组特殊情况。根据应用程序的需求,信号可能会被忽略,被认为是信息性的或被视为异常。十进制模块中的信号是:Clamped,InvalidOperation, DivisionByZero,Inexact,Rounded,Subnormal, Overflow,Underflow和FloatOperation。

对于每个信号,都有一个标志和一个陷阱使能器。遇到信号时,其标志设置为1,然后,如果陷阱启用器设置为1,则会引发异常。标志是粘性的,因此用户需要在监视计算之前将其重置。

也可以看看
IBM的通用十进制算术规范,通用十进制算术规范。

快速入门教程
使用小数的通常开始是导入模块,使用getcontext()和查看当前上下文,并在必要时设置精度,舍入或启用陷阱的新值:

>>>
>>> from decimal import *
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
        capitals=1, clamp=0, flags=[], traps=[Overflow, DivisionByZero,
        InvalidOperation])

>>> getcontext().prec = 7       # Set a new precision
十进制实例可以由整数,字符串,浮点数或元组构造。从整数或浮点数进行构造会对该整数或浮点数的值进行精确转换。十进制数包括特殊值,例如 NaN代表“非数字”,正数和负数 Infinity,以及-0:

>>>
>>> getcontext().prec = 28
>>> Decimal(10)
Decimal('10')
>>> Decimal('3.14')
Decimal('3.14')
>>> Decimal(3.14)
Decimal('3.140000000000000124344978758017532527446746826171875')
>>> Decimal((0, (3, 1, 4), -2))
Decimal('3.14')
>>> Decimal(str(2.0 ** 0.5))
Decimal('1.4142135623730951')
>>> Decimal(2) ** Decimal('0.5')
Decimal('1.414213562373095048801688724')
>>> Decimal('NaN')
Decimal('NaN')
>>> Decimal('-Infinity')
Decimal('-Infinity')
如果FloatOperation信号被捕获,则在构造函数或顺序比较中意外混合小数和浮点数将引发异常:

>>>
>>> c = getcontext()
>>> c.traps[FloatOperation] = True
>>> Decimal(3.14)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
decimal.FloatOperation: [<class 'decimal.FloatOperation'>]
>>> Decimal('3.5') < 3.7
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
decimal.FloatOperation: [<class 'decimal.FloatOperation'>]
>>> Decimal('3.5') == 3.5
True
版本3.3中的新功能。

新十进制的重要性仅由输入的位数确定。上下文精度和舍入仅在算术运算中起作用。

>>> getcontext().prec = 6
>>> Decimal('3.0')
Decimal('3.0')
>>> Decimal('3.1415926535')
Decimal('3.1415926535')
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85987')
>>> getcontext().rounding = ROUND_UP
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85988')
如果超过了C版本的内部限制,则构造一个十进制数将引发InvalidOperation:

>>>
>>> Decimal("1e9999999999999999999")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]
在版本3.3中更改。

小数与其他大部分Python交互良好。这是一个小的十进制浮点飞行马戏团:

>>> data = list(map(Decimal, '1.34 1.87 3.45 2.35 1.00 0.03 9.25'.split()))
>>> max(data)
Decimal('9.25')
>>> min(data)
Decimal('0.03')
>>> sorted(data)
[Decimal('0.03'), Decimal('1.00'), Decimal('1.34'), Decimal('1.87'),
Decimal('2.35'), Decimal('3.45'), Decimal('9.25')]
>>> sum(data)
Decimal('19.29')
>>> a,b,c = data[:3]
>>> str(a)
'1.34'
>>> float(a)
1.34
>>> round(a, 1)
Decimal('1.3')
>>> int(a)
1
>>> a * 5
Decimal('6.70')
>>> a * b
Decimal('2.5058')
>>> c % a
Decimal('0.77')
还有一些数学函数可用于Decimal:

getcontext().prec = 28
Decimal(2).sqrt()
Decimal('1.414213562373095048801688724')
Decimal(1).exp()
Decimal('2.718281828459045235360287471')
Decimal('10').ln()
Decimal('2.302585092994045684017991455')
Decimal('10').log10()
Decimal('1')
该quantize()方法将数字四舍五入为固定的指数。此方法对于经常将结果舍入到固定位数的货币应用程序很有用:

Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32')
Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)
Decimal('8')
如上所示,该getcontext()函数访问当前上下文并允许更改设置。这种方法可以满足大多数应用程序的需求。

对于更高级的工作,使用Context()构造函数创建备用上下文可能会很有用。要启用备用setcontext() 功能,请使用该功能。

根据该标准,该decimal模块提供了两个准备使用的标准上下文,BasicContext和ExtendedContext。前者对于调试特别有用,因为启用了许多陷阱:

>>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN)
>>> setcontext(myothercontext)
>>> Decimal(1) / Decimal(7)
Decimal('0.142857142857142857142857142857142857142857142857142857142857')

>>> ExtendedContext
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
        capitals=1, clamp=0, flags=[], traps=[])
>>> setcontext(ExtendedContext)
>>> Decimal(1) / Decimal(7)
Decimal('0.142857143')
>>> Decimal(42) / Decimal(0)
Decimal('Infinity')

>>> setcontext(BasicContext)
>>> Decimal(42) / Decimal(0)
Traceback (most recent call last):
  File "<pyshell#143>", line 1, in -toplevel-
    Decimal(42) / Decimal(0)
DivisionByZero: x / 0
上下文还具有用于监视计算过程中遇到的异常情况的信号标志。这些标志将保持设置状态直到被明确清除为止,因此最好使用该clear_flags()方法在每组监视的计算之前清除这些标志。

>>>
>>> setcontext(ExtendedContext)
>>> getcontext().clear_flags()
>>> Decimal(355) / Decimal(113)
Decimal('3.14159292')
>>> getcontext()
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
        capitals=1, clamp=0, flags=[Inexact, Rounded], traps=[])
该标志条目显示合理的近似Pi四舍五入(数字超出范围内精度被扔掉了),而且结果不准确(有些丢弃数字为非零)。

使用traps上下文上下文中的字典设置各个陷阱:

>>> setcontext(ExtendedContext)
>>> Decimal(1) / Decimal(0)
Decimal('Infinity')
>>> getcontext().traps[DivisionByZero] = 1
>>> Decimal(1) / Decimal(0)
Traceback (most recent call last):
  File "<pyshell#112>", line 1, in -toplevel-
    Decimal(1) / Decimal(0)
DivisionByZero: x / 0
大多数程序在程序开始时仅调整一次当前上下文。而且,在许多应用程序中,数据Decimal通过循环内的一次转换进行转换。创建上下文集和创建小数后,程序的大部分操作数据便与使用其他Python数字类型一样。

小数对象
类decimal.Decimal(value =“ 0”,context = None )
Decimal根据value构造一个新对象。

值可以是整数,字符串,元组float,或其他Decimal 对象。如果没有给出值,则返回Decimal('0')。如果value是一个字符串,则删除前导和尾随空格字符以及整个下划线后,它应符合十进制数字字符串语法:

sign           ::=  '+' | '-'
digit          ::=  '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
indicator      ::=  'e' | 'E'
digits         ::=  digit [digit]...
decimal-part   ::=  digits '.' [digits] | ['.'] digits
exponent-part  ::=  indicator [sign] digits
infinity       ::=  'Infinity' | 'Inf'
nan            ::=  'NaN' [digits] | 'sNaN' [digits]
numeric-value  ::=  decimal-part [exponent-part] | infinity
numeric-string ::=  [sign] numeric-value | [sign] nan
digit 上面显示的地方也可以使用其他Unicode小数位。这些包括从各种其它字母(例如,阿拉伯-印度文和梵文位数)与全角数字沿十进制数字'\uff10'通过'\uff19'。

如果value是a tuple,则它应包含三个部分,一个符号(0正数或1负数),一个tuple数字a 和一个整数指数。例如, return 。Decimal((0, (1, 4, 1, 4), -3))Decimal('1.414')

如果value为a float,则二进制浮点值将无损地转换为其精确的十进制等效值。这种转换通常需要53位或更多位数的精度。例如,Decimal(float('1.1')) 将转换为 Decimal('1.100000000000000088817841970012523233890533447265625')。

该背景下的精度并不影响多少位被存储。这完全取决于值的位数。例如,Decimal('3.00000')即使上下文精度仅为3 ,也 记录所有五个零。

上下文参数的目的是确定如果value是格式错误的字符串该怎么办。如果上下文陷阱InvalidOperation,则会引发异常;否则,将引发异常。否则,构造函数将返回值为的新Decimal NaN。

一旦构造,Decimal对象是不可变的。

在版本3.2中更改:现在允许将构造函数的参数作为float 实例。

在版本3.3中进行了更改:float如果FloatOperation 设置了陷阱,则参数会引发异常。默认情况下,陷阱处于关闭状态。

在版本3.6中更改:与代码中的整数和浮点文字一样,允许使用下划线进行分组。

十进制浮点对象与其他内置数字类型(例如float和)共享许多属性int。所有常用的数学运算和特殊方法都适用。同样,十进制对象可以被复制,腌制,打印,用作字典键,用作集合元素,进行比较,排序和强制转换为另一种类型(例如float或 int)。

小数对象的算术与整数和浮点数的算术之间有一些细微的差异。当余数运算符%应用于十进制目的,结果的符号是的符号 被除数而不是除数的符号:

>>>
>>> (-7) % 4
1
>>> Decimal(-7) % Decimal(4)
Decimal('-3')
整数除法运算符的//行为类似,返回真商的整数部分(向零截断)而不是其下限,以便保留通常的标识:x == (x // y) * y + x % y

>>>
>>> -7 // 4
-2
>>> Decimal(-7) // Decimal(4)
Decimal('-1')
的%和//运营商实现remainder和 divide-integer操作(分别)如说明书中所述。

小数对象通常不能与浮点数或fractions.Fraction算术运算符的实例结合使用:例如,将a Decimal加到a 的尝试float将引发a TypeError。但是,可以使用Python的比较运算符将一个Decimal 实例x与另一个number 进行比较y。这样可以避免在对不同类型的数字进行相等比较时混淆结果。

在版本3.2中进行了更改:Decimal现在完全支持实例与其他数字类型之间的混合类型比较。

除标准数值属性外,十进制浮点对象还具有许多专用方法:

adjusted()
移出系数的最右边数字后,返回调整后的指数,直到仅剩下前导数字为止: Decimal('321e+5').adjusted()返回7。用于确定最高有效数字相对于小数点的位置。

as_integer_ratio()
返回一对整数,这些整数以最小的分数和一个正的分母将给定实例表示 为分数:(n, d)Decimal

>>>
>>> Decimal('-3.14').as_integer_ratio()
(-157, 50)
转换是精确的。提高Infinities的OverflowError和NaN的ValueError。

3.6版的新功能。

as_tuple()
返回数字的命名元组表示形式 。DecimalTuple(sign, digits, exponent)

canonical()
返回参数的规范编码。当前,Decimal实例的编码始终是规范的,因此此操作返回其参数不变。

compare(其他,context = None )
比较两个十进制实例的值。 compare()返回一个Decimal实例,并且如果其中一个操作数为NaN,则结果为NaN:

a or b is a NaN  ==> Decimal('NaN')
a < b            ==> Decimal('-1')
a == b           ==> Decimal('0')
a > b            ==> Decimal('1')
compare_signal(其他,context = None )
compare()除了所有NaNs信号外,该操作与方法相同。也就是说,如果两个操作数都不是信令NaN,则将任何安静的NaN操作数都视为信令NaN。

compare_total(其他,context = None )
使用它们的抽象表示而不是数值比较两个操作数。与compare()方法相似,但是结果给出了Decimal实例的总顺序。Decimal具有相同数值但表示形式不同的两个 实例按以下顺序比较不相等:

Decimal('12.0').compare_total(Decimal('12'))
Decimal('-1')
安静和信令NaN也包括在总排序中。此函数的结果是Decimal('0')两个操作数具有相同的表示形式,Decimal('-1')如果第一个操作数的总顺序比第二个操作数的总顺序低,并且Decimal('1')第一个操作数的总顺序比第二个操作数的总顺序高。有关总订单的详细信息,请参见规格。

该操作不受上下文的影响,并且很安静:不更改标志且不执行舍入。作为例外,如果不能精确转换第二个操作数,则C版本可能会引发InvalidOperation。

compare_total_mag(其他,context = None )
使用它们的抽象表示来比较两个操作数,而不是像中的那样比较它们的值compare_total(),但忽略每个操作数的符号。 x.compare_total_mag(y)等同于 x.copy_abs().compare_total(y.copy_abs())。

该操作不受上下文的影响,并且很安静:不更改标志且不执行舍入。作为例外,如果不能精确转换第二个操作数,则C版本可能会引发InvalidOperation。

conjugate()
只是返回自身,此方法仅符合十进制规范。

copy_abs()
返回参数的绝对值。此操作不受上下文的影响,并且是安静的:不更改标志且不执行舍入。

copy_negate()
返回参数的取反。此操作不受上下文的影响,并且是安静的:不更改标志且不执行舍入。

copy_sign(其他,context = None )
返回第一个操作数的副本,其符号设置为与第二个操作数的符号相同。例如:

Decimal('2.3').copy_sign(Decimal('-1.5'))
Decimal('-2.3')
该操作不受上下文的影响,并且很安静:不更改标志且不执行舍入。作为例外,如果不能精确转换第二个操作数,则C版本可能会引发InvalidOperation。

exp(context = None )
返回e**x给定数字的(自然)指数函数的值。使用ROUND_HALF_EVEN舍入模式可以正确舍入结果 。

Decimal(1).exp()
Decimal('2.718281828459045235360287471')
Decimal(321).exp()
Decimal('2.561702493119680037517373933E+139')
from_float(f )
精确地将浮点数转换为十进制数的类方法。

注意Decimal.from_float(0.1)与Decimal('0.1')不同。由于在二进制浮点中不能精确表示0.1,因此该值存储为最接近的可表示值 0x1.999999999999ap-4。十进制的等效值是 0.1000000000000000055511151231257827021181583404541015625。

注意 从Python 3.2开始,Decimal实例也可以直接从构造float。
>>> Decimal.from_float(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
>>> Decimal.from_float(float('nan'))
Decimal('NaN')
>>> Decimal.from_float(float('inf'))
Decimal('Infinity')
>>> Decimal.from_float(float('-inf'))
Decimal('-Infinity')
3.1版中的新功能。

fma(other,第三,context = None )
融合乘法加法。返回自身*其他+第三,中间产品自身*其他不四舍五入。

Decimal(2).fma(3, 5)
Decimal('11')
is_canonical()
True如果参数是规范的,False 则返回,否则返回。当前,Decimal实例始终是规范的,因此该操作始终返回True。

is_finite()
返回True如果参数是一个有限数量,以及 False如果参数为无穷大或为NaN。

is_infinite()
返回True如果参数为正或负无穷大,False否则。

is_nan()
True如果参数是(安静或信令)NaN,False则返回, 否则返回。

is_normal(context = None )
True如果参数是一个普通的有限数,则返回。返回 False如果参数为0,低于正常,无穷大或NaN的。

is_qnan()
True如果参数是一个安静的NaN,则返回, False否则返回。

is_signed()
True如果参数为负号,False则返回, 否则返回。请注意,零和NaN都可以携带符号。

is_snan()
True如果参数是信令NaN,False 则返回,否则返回。

is_subnormal(context = None )
True如果参数是次正规的,则返回,False 否则返回。

is_zero()
True如果参数为(正或负)零,False则返回, 否则返回。

ln(context = None )
返回操作数的自然对数(以e为底)。使用ROUND_HALF_EVEN舍入模式可以正确舍入结果。

log10(context = None )
返回操作数的以10为底的对数。使用ROUND_HALF_EVEN舍入模式可以正确舍入结果。

logb(context = None )
对于非零数,返回其操作数的调整后的指数作为 Decimal实例。如果操作数为零,则Decimal('-Infinity')返回操作数 并DivisionByZero引发标志。如果操作数是无穷大,则Decimal('Infinity')返回。

logical_and(其他,context = None )
logical_and()是一个逻辑操作,它接受两个逻辑操作数(请参阅逻辑操作数)。结果是and两个操作数的按位运算。

logical_invert(context = None )
logical_invert()是逻辑操作。结果是操作数的按位求逆。

logical_or(其他,context = None )
logical_or()是一个逻辑操作,它接受两个逻辑操作数(请参阅逻辑操作数)。结果是or两个操作数的按位运算。

logical_xor(其他,context = None )
logical_xor()是一个逻辑操作,它接受两个逻辑操作数(请参阅逻辑操作数)。结果是两个操作数的按位异或。

max(其他,context = None )
与之类似,只是上下文舍入规则在返回之前应用,并且值被信号通知或忽略(取决于上下文以及它们是信令还是安静)。max(self, other)NaN

max_mag(其他,context = None )
与max()方法类似,但是比较是使用操作数的绝对值完成的。

min(其他,context = None )
与之类似,只是上下文舍入规则在返回之前应用,并且值被信号通知或忽略(取决于上下文以及它们是信令还是安静)。min(self, other)NaN

min_mag(其他,context = None )
与min()方法类似,但是比较是使用操作数的绝对值完成的。

next_minus(context = None )
返回小于给定操作数的给定上下文(如果没有给定上下文,则在当前线程的上下文中)可表示的最大数字。

next_plus(context = None )
返回大于给定操作数的,在给定上下文(如果没有给定上下文,则在当前线程的上下文)中可表示的最小数字。

next_toward(其他,context = None )
如果两个操作数不相等,则在第二个操作数的方向上返回最接近第一个操作数的数字。如果两个操作数在数值上相等,则返回第一个操作数的副本,其符号设置为与第二个操作数的符号相同。

normalize(context = None )
通过去除最右边的尾随零并转换等于的任何结果来Decimal('0')对 数字进行归一化Decimal('0e0')。用于为等效类的属性生成规范值。例如,Decimal('32.100')和 Decimal('0.321000e+2')都标准化为等效值 Decimal('32.1')。

number_class(context = None )
返回描述操作数类的字符串。返回的值是以下十个字符串之一。

"-Infinity",指示操作数为负无穷大。

"-Normal",指示操作数为负正数。

"-Subnormal",表示操作数为负且不正常。

"-Zero",指示操作数为负零。

"+Zero",表示操作数为正零。

"+Subnormal",表示操作数是正数和次正规数。

"+Normal",表示操作数为正数。

"+Infinity",指示操作数为正无穷大。

"NaN",表示操作数是一个安静的NaN(不是数字)。

"sNaN",指示操作数是信令NaN。

quantize(exp,取整=无,上下文=无)
四舍五入后,返回等于第一个操作数的值,并具有第二个操作数的指数。

Decimal('1.41421356').quantize(Decimal('1.000'))
Decimal('1.414')
与其他运算不同,如果量化运算之后的系数长度大于精度,则会 InvalidOperation发出信号。这样可以保证,除非有错误情况,否则量化的指数始终等于右侧操作数的指数。

同样与其他操作不同,即使结果不合标准且不精确,量化也永远不会表示下溢。

如果第二个操作数的指数大于第一个操作数的指数,则可能需要舍入。在这种情况下,舍入模式由rounding给定的参数确定,否则由给定的 context参数确定;如果两个参数都没有给出,则使用当前线程上下文的舍入模式。

每当结果指数大于Emax或小于时,都会返回错误 Etiny。

radix()
返回Decimal(10),Decimal 该类在其中进行所有算术运算的基数(基数)。包括在内是为了与规范兼容。

remainder_near(其他,context = None )
从自我除以他人的回报。这与 选择余数的符号以使其绝对值最小化不同。更精确地,返回值是 其中是最接近的精确值的整数,如果两个整数相等,则选择偶数。self % otherself - n * othernself / other

如果结果为零,则其符号将为self的符号。

Decimal(18).remainder_near(Decimal(10))
Decimal('-2')
Decimal(25).remainder_near(Decimal(10))
Decimal('5')
Decimal(35).remainder_near(Decimal(10))
Decimal('-5')
rotate(其他,context = None )
返回将第一个操作数的位数旋转第二个操作数指定的数量的结果。第二个操作数必须是-precision至precision范围内的整数。第二个操作数的绝对值给出旋转的位数。如果第二个操作数为正,则向左旋转;否则,向左旋转。否则旋转向右。如有必要,第一个操作数的系数在左侧填充零以达到长度精度。第一个操作数的符号和指数不变。

same_quantum(其他,context = None )
测试self和other是否具有相同的指数,或者两者都相同 NaN。

该操作不受上下文的影响,并且很安静:不更改标志且不执行舍入。作为例外,如果不能精确转换第二个操作数,则C版本可能会引发InvalidOperation。

scaleb(其他,context = None )
返回第一个操作数,其指数由第二个调整。等效地,返回第一个操作数乘以10**other。第二个操作数必须是整数。

shift(其他,context = None )
返回将第一个操作数的位数移位第二个操作数指定的数量的结果。第二个操作数必须是-precision至precision范围内的整数。第二个操作数的绝对值给出移位的位数。如果第二个操作数为正,则向左移动;否则,向左移动。否则,移动将向右移动。移入系数的数字为零。第一个操作数的符号和指数不变。

sqrt(context = None )
将参数的平方根返回全精度。

to_eng_string(context = None )
如果需要指数,请使用工程符号转换为字符串。

工程符号的指数是3的倍数。这最多可以在小数点左边留下3位数字,并且可能需要添加一个或两个尾随零。

例如,这将转换Decimal('123E+1')为Decimal('1.23E+3')。

to_integral(rounding = None,context = None )
与to_integral_value()方法相同。to_integral 保留该名称是为了与旧版本兼容。

to_integral_exact(rounding = None,context = None )
四舍五入到最接近的整数,用信号通知Inexact或 Rounded在发生舍入时酌情进行。舍入模式由rounding参数(如果给定)确定,否则由给定 context。如果没有给出任何参数,则使用当前上下文的舍入模式。

to_integral_value(rounding = None,context = None )
舍入到最接近的整数而不用信号Inexact或 Rounded。如果给定,则应用舍入;否则,在提供的上下文或当前上下文中使用舍入方法。

逻辑操作数
在logical_and(),logical_invert(),logical_or(),和logical_xor()方法,希望他们的论点是合乎逻辑的操作数。一个合乎逻辑的操作数是一个Decimal实例,其指数和符号均为零,而其数字都是要么 0或1。

上下文对象
上下文是算术运算的环境。它们控制精度,设置舍入规则,确定哪些信号被视为异常,并限制指数范围。

每个线程都有自己的当前上下文,可以使用getcontext()和setcontext()函数访问或更改它们 :

decimal.getcontext()
返回活动线程的当前上下文。

decimal.setcontext(c )
将活动线程的当前上下文设置为c。

您还可以使用该with语句和该localcontext() 函数临时更改活动上下文。

decimal.localcontext(ctx = None )
返回一个上下文管理器,该上下文管理器将在进入with语句时将活动线程的当前上下文设置为ctx的副本,并在退出with语句时恢复先前的上下文。如果未指定上下文,则使用当前上下文的副本。

例如,以下代码将当前的十进制精度设置为42位,执行计算,然后自动恢复先前的上下文:

from decimal import localcontext

with localcontext() as ctx:
    ctx.prec = 42   # Perform a high precision calculation
    s = calculate_something()
s = +s  # Round the final result back to the default precision
也可以使用Context下面描述的构造函数创建新的上下文。此外,该模块提供了三个预制的上下文:

类decimal.BasicContext
这是通用十进制算术规范定义的标准上下文。精度设置为九。舍入设置为 ROUND_HALF_UP。所有标志被清除。除,和 之外Inexact,所有陷阱均已启用(被视为例外)。RoundedSubnormal

因为启用了许多陷阱,所以此上下文对于调试很有用。

类decimal.ExtendedContext
这是通用十进制算术规范定义的标准上下文。精度设置为九。舍入设置为 ROUND_HALF_EVEN。所有标志被清除。没有启用陷阱(因此在计算过程中不会引发异常)。

因为禁用了陷阱,所以此上下文对于希望结果值为NaN或Infinity代替引发异常的应用程序很有用。这允许应用程序在可能会导致程序停止的条件下完成运行。

类decimal.DefaultContext
Context构造函数将此上下文用作新上下文的原型。更改字段(这样的精度)具有更改Context构造函数创建的新上下文的默认值的效果。

此上下文在多线程环境中最有用。在启动线程之前更改字段之一会影响设置系统范围的默认值。不建议在线程启动后更改字段,因为这将需要线程同步以防止出现竞争状况。

在单线程环境中,最好完全不使用此上下文。相反,只需按如下所述显式创建上下文即可。

默认值是prec= 28, rounding= ROUND_HALF_EVEN,并启用陷阱Overflow,InvalidOperation和 DivisionByZero。

除了提供的三个上下文外,还可以使用Context构造函数创建新的上下文 。

类decimal.Context(prec = None,取整= None,Emin = None,Emax = None,大写= None,钳位= None,flags = None,traps = None )
创建一个新的上下文。如果未指定字段None,则从中复制默认值DefaultContext。如果 未指定flags字段或为None,则将清除所有标志。

prec是[ 1,MAX_PREC] 范围内的整数,用于设置上下文中算术运算的精度。

舍入选项是“ 舍入模式 ”部分中列出的常量之一 。

该陷阱和标志字段列出任何信号进行设置。通常,新上下文仅应设置陷阱,并清除标志。

的额敏和的Emax字段是允许指定外部界限为指数的整数。额敏必须在范围[ MIN_EMIN,0] 的Emax在范围[ 0,MAX_EMAX]。

的首都字段是0或1(缺省值)。如果设置为 1指数则用大写字母表示E; 否则,使用小写字母e:Decimal('6.02e+23')。

所述夹具字段是0(缺省值)或1。如果设置为1,则 在此上下文中可表示e的Decimal实例的指数严格限制在该范围内。如果钳位是 一个较弱的条件,则实例的调整指数最大为Emin - prec + 1 <= e <= Emax - prec + 10DecimalEmax。当钳是 1,大量正常数量将在可能情况下,具有其指数降低,并且添加到它的系数,以拟合指数约束零的相应号码; 这样可以保留数字的值,但是会丢失有关尾随零的信息。例如:

>>>
>>> Context(prec=6, Emax=999, clamp=1).create_decimal('1.23e999')
Decimal('1.23000E+999')
甲钳位的值1允许与IEEE 754中指定的固定宽度的小数交换格式的兼容性。

在Context类定义了几个通用的方法,以及用于在特定情况下做算术直接了大量的方法。此外,对于Decimal上述每种方法(adjusted()和和as_tuple()方法除外),都有相应的Context方法。例如,对于一个Context 实例C和Decimal实例x,C.exp(x)等效于x.exp(context=C)。每个Context方法在接受intDecimal实例的任何地方都接受一个Python整数(的一个实例)。

clear_flags()
将所有标志重置为0。

clear_traps()
将所有陷阱重置为0。

版本3.3中的新功能。

copy()
返回上下文的副本。

copy_decimal(num )
返回Decimal实例num的副本。

create_decimal(num )
从num创建一个新的Decimal实例,但使用self作为上下文。与Decimal构造函数不同,上下文精度,舍入方法,标志和陷阱将应用于转换。

这很有用,因为常量通常比应用程序需要的精度更高。另一个好处是,舍入可以立即消除数字超出当前精度的意外影响。在下面的示例中,使用非四舍五入的输入意味着将零加到总和上可以更改结果:

>>> getcontext().prec = 3
>>> Decimal('3.4445') + Decimal('1.0023')
Decimal('4.45')
>>> Decimal('3.4445') + Decimal(0) + Decimal('1.0023')
Decimal('4.44')
该方法实现了IBM规范的数字运算。如果参数是字符串,则不允许前导或尾随空格或下划线。

create_decimal_from_float(f )
从float f创建一个新的Decimal实例,但使用self 作为上下文进行舍入。与Decimal.from_float()类方法不同,上下文精度,舍入方法,标志和陷阱将应用于转换。

>>> context = Context(prec=5, rounding=ROUND_DOWN)
>>> context.create_decimal_from_float(math.pi)
Decimal('3.1415')
>>> context = Context(prec=5, traps=[Inexact])
>>> context.create_decimal_from_float(math.pi)
Traceback (most recent call last):
    ...
decimal.Inexact: None
3.1版中的新功能。

Etiny()
返回等于次正规结果的最小指数值的值。当发生下溢时,指数设置为。Emin - prec + 1Etiny

Etop()
返回等于的值。Emax - prec + 1

处理小数的通常方法是创建Decimal 实例,然后对活动线程应用在当前上下文内发生的算术运算。一种替代方法是使用上下文方法在特定上下文中进行计算。这些方法与Decimal该类的方法相似,在此仅作简要介绍。

abs(x )
返回x的绝对值。

add(x,y )
返回x和y的总和。

canonical(x )
返回相同的Decimal对象x。

compare(x,y )
数字比较x和y。

compare_signal(x,y )
数字比较两个操作数的值。

compare_total(x,y )
使用它们的抽象表示比较两个操作数。

compare_total_mag(x,y )
使用它们的抽象表示比较两个操作数,而忽略符号。

copy_abs(x )
返回x的副本符号设置为0。

copy_negate(x )
返回x的副本其中符号取反。

copy_sign(x,y )
将符号从y复制到x。

divide(x,y )
返回x除以y。

divide_int(x,y )
返回x除以y,截断为整数。

divmod(x,y )
除以两个数字并返回结果的整数部分。

exp(x )
返回e ** x。

fma(x,y, z )
返回x乘以y加上z。

is_canonical(x)
返回True如果X是规范的; 否则返回False。

is_finite(x )
True如果x是有限的,则返回 否则返回False。

is_infinite(x )
True如果x是无限的,则返回;否则返回false。否则返回False。

is_nan(x )
返回True如果X是QNAN或SNAN; 否则返回False。

is_normal(x )
返回True如果X是一个正常数; 否则返回False。

is_qnan(x )
返回x是否为安静的NaN;True否则返回false。否则返回False。

is_signed(x)
True如果x为负,则返回;否则为false。否则返回False。

is_snan(x)
True如果x是一个信令NaN,则返回;否则返回false。否则返回False。

is_subnormal(x)
返回True如果X是低于正常; 否则返回False。

is_zero(x )
返回True如果X是零; 否则返回False。

ln(x )
返回x的自然(以e为底)对数。

log10(x )
返回x的以10为底的对数。

logb(x )
返回操作数的MSD大小的指数。

logical_and(x,y )
应用逻辑运算和每个操作数的数字之间。

logical_invert(x)
反转x中的所有数字。

logical_or(x,y)
应用逻辑运算或在每个操作数的数字之间。

logical_xor(x,y)
在每个操作数的数字之间应用逻辑运算“ 异或”。

max(x,y)
数字比较两个值并返回最大值。

max_mag(x,y)
通过数值比较数值并将其符号忽略。

min(x,y )
数字比较两个值并返回最小值。

min_mag(x,y )
通过数值比较数值并将其符号忽略。

minus(x )
Minus对应于Python中的一元前缀减号运算符。

multiply(x,y )
返回x和y的乘积。

next_minus(x )
返回小于x的最大可表示数字。

next_plus(x )
返回大于x的最小可表示数字。

next_toward(x,y )
返回朝y方向最接近x的数字。

normalize(x )
将x简化为最简单的形式。

number_class(x )
返回x类别的指示。

plus(x )
加号对应于Python中的一元前缀加号运算符。此操作应用上下文精度和舍入,因此它不是身份操作。

power(x,y,modulo = None )
返回x给定的幂y,减少模数modulo。

有两个参数,compute x**y。如果x为负,则y 必须为整数。除非y是整数且结果是有限的并且可以用“精度”数字精确表示,否则结果将是不精确的。使用上下文的舍入模式。结果始终在Python版本中正确取整。

在版本3.3中更改: C模块根据power()正确取整 exp()和ln()函数进行计算。结果定义明确,但“几乎总是正确取整”。

使用三个参数,compute 。对于三个参数形式,对参数的以下限制适用:(x**y) % modulo

这三个参数都必须是整数

y 必须为非负数

至少一个x或y必须为非零

modulo 必须为非零且最多具有“精度”数字

产生的值等于以无限精度进行计算而获得的值,但计算效率更高。结果的指数是零,不管的指数,和。结果总是准确的。Context.power(x, y, modulo)(x**y) % moduloxymodulo

quantize(x,y )
返回一个值等于X(圆形),具有的指数&#255;。

radix()
仅返回10,因为这是十进制,:)

remainder(x,y )
返回整数除法的余数。

结果的符号(如果非零)与原始除数的符号相同。

remainder_near(x,y )
返回,其中n是最接近其确切值的整数(如果结果为0,则其符号将为x的符号)。x - y * nx / y

rotate(x,y )
返回x,y次的旋转副本。

same_quantum(x,y )
True如果两个操作数具有相同的指数,则返回。

scaleb(x,y )
将第二个值与其exp相加后,返回第一个操作数。

shift(x,y )
返回x,y次的移位副本。

sqrt(x )
非负数的平方根到上下文精度。

subtract(x,y )
返回x和y之间的差。

to_eng_string(x )
如果需要指数,请使用工程符号转换为字符串。

工程符号的指数是3的倍数。这最多可以在小数点左边留下3位数字,并且可能需要添加一个或两个尾随零。

to_integral_exact(x )
四舍五入为整数。

to_sci_string(x )
使用科学计数法将数字转换为字符串。

常数
本节中的常量仅与C模块有关。它们也包含在纯Python版本中以实现兼容性。

32位

64位

decimal.MAX_PREC
425000000

999999999999999999

decimal.MAX_EMAX
425000000

999999999999999999

decimal.MIN_EMIN
-425000000

-999999999999999999

decimal.MIN_ETINY
-849999999

-1999999999999999997

decimal.HAVE_THREADS
默认值为True。如果Python是在没有线程的情况下编译的,则C版本会自动禁用昂贵的线程本地上下文机制。在这种情况下,值是False。

舍入模式
decimal.ROUND_CEILING
朝方向走Infinity。

decimal.ROUND_DOWN
向零舍入。

decimal.ROUND_FLOOR
朝方向走-Infinity。

decimal.ROUND_HALF_DOWN
四舍五入到最接近的零关系。

decimal.ROUND_HALF_EVEN
四舍五入到最接近的关系,领带接近最接近的偶数整数。

decimal.ROUND_HALF_UP
四舍五入到最接近的关系,领带的距离从零开始。

decimal.ROUND_UP
四舍五入。

decimal.ROUND_05UP
如果四舍五入后的最后一位数字为0或5,则从零舍入。否则舍入为零。

讯号
信号代表在计算过程中出现的条件。每个对应一个上下文标志和一个上下文陷阱启用器。

只要遇到条件,就设置上下文标志。计算之后,出于信息目的(例如,确定计算是否准确)可以检查标志。检查标志后,请确保在开始下一次计算之前清除所有标志。

如果为信号设置了上下文的陷阱启用器,则该条件将引发Python异常。例如,如果DivisionByZero设置了陷阱,则DivisionByZero在遇到条件时会引发异常。

类decimal.Clamped
更改了指数以适合表示约束。

通常,当指数超出上下文的范围Emin和Emax界限时,会发生钳位 。如有可能,可通过在系数上加上零来减小指数以使其拟合。

类decimal.DecimalException
其他信号的基类和的子类ArithmeticError。

类decimal.DivisionByZero
表示将非无限数除以零。

可能发生除法,模除或将数字加到负幂的情况。如果未捕获此信号,则返回Infinity或 -Infinity带有由计算输入确定的符号。

类decimal.Inexact
表示发生了舍入并且结果不准确。

在舍入过程中丢弃非零数字时发出信号。舍入结果返回。信号标志或陷阱用于检测结果不准确的时间。

类decimal.InvalidOperation
执行了无效的操作。

表示请求的操作没有意义。如果没有被捕获,则返回NaN。可能的原因包括:

Infinity - Infinity
0 * Infinity
Infinity / Infinity
x % 0
Infinity % x
sqrt(-x) and x > 0
0 ** 0
x ** (non-integer)
x ** Infinity
类decimal.Overflow
数值溢出。

表示指数大于Emax四舍五入后的数值。如果未捕获,则结果取决于舍入模式,是向内拉到可表示的最大有限数,还是向外舍入到Infinity。在这两种情况下,Inexact并Rounded 也发出信号。

类decimal.Rounded
尽管可能没有丢失任何信息,但仍进行了四舍五入。

当舍入舍弃数字时发出信号;即使这些数字为零(例如,四舍五入5.00为5.0)。如果未捕获,则返回结果不变。该信号用于检测有效数字的丢失。

类decimal.Subnormal
指数低于Emin四舍五入之前的水平。

当运算结果不正常(指数太小)时发生。如果未捕获,则返回结果不变。

类decimal.Underflow
数字下溢,结果四舍五入到零。

通过舍入将非正规结果推为零时发生。Inexact 并且Subnormal也发出信号

类decimal.FloatOperation
为混合浮点数和十进制数启用更严格的语义。

如果未捕获信号(默认),则在Decimal构造函数 create_decimal()和所有比较运算符中允许混合使用float和Decimals 。转换和比较都是准确的。通过FloatOperation在上下文标志中设置静默记录任何混合操作的发生。使用from_float() 或create_decimal_from_float()不设置标志的显式转换。

否则(信号被捕获),只有相等比较和显式转换是静默的。其他所有混合作业都会增加FloatOperation。

下表总结了信号的层次结构:

exceptions.ArithmeticError(exceptions.Exception)
    DecimalException
        Clamped
        DivisionByZero(DecimalException, exceptions.ZeroDivisionError)
        Inexact
            Overflow(Inexact, Rounded)
            Underflow(Inexact, Rounded, Subnormal)
        InvalidOperation
        Rounded
        Subnormal
        FloatOperation(DecimalException, exceptions.TypeError)
浮点注释
以更高的精度缓解舍入误差
使用十进制浮点数消除了十进制表示错误(可以表示 0.1精确)。但是,当非零数字超出固定精度时,某些操作仍然会产生舍入错误。

舍入误差的影响可以通过相加或相减几乎抵消的量来放大,从而导致重要性下降。Knuth提供了两个说明性示例,其中精度不够高的舍入浮点运算会导致加法的关联和分布性质崩溃:

# Examples from Seminumerical Algorithms, Section 4.2.2.
>>> from decimal import Decimal, getcontext
>>> getcontext().prec = 8

>>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
>>> (u + v) + w
Decimal('9.5111111')
>>> u + (v + w)
Decimal('10')

>>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
>>> (u*v) + (u*w)
Decimal('0.01')
>>> u * (v+w)
Decimal('0.0060000')
该decimal模块可以通过充分扩展精度以避免丢失重要性来恢复身份:

>>> getcontext().prec = 20
>>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
>>> (u + v) + w
Decimal('9.51111111')
>>> u + (v + w)
Decimal('9.51111111')
>>>
>>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
>>> (u*v) + (u*w)
Decimal('0.0060000')
>>> u * (v+w)
Decimal('0.0060000')
特殊值
对于数字系统decimal模块提供了特殊的值,包括NaN,sNaN,-Infinity,Infinity,和两个零,+0和-0。

无限性可以直接使用构造 Decimal('Infinity')。同样,当DivisionByZero信号未被捕获时,它们可能由零除而产生。同样,当Overflow信号没有被捕获时,由于舍入超出最大可表示数的限制而可能导致无穷大。

无穷大是有符号的(仿射),可以在算术运算中使用,将它们视为非常大的不确定数字。例如,将常数添加到无穷大会得到另一个无穷大的结果。

某些操作不确定并返回NaN,或者如果InvalidOperation捕获了 信号,则引发异常。例如, 0/0返回NaN表示“不是数字”。这种变化 NaN是安静的,一旦创建,将流经其他计算,总是产生另一个NaN。此行为对于偶尔缺少输入的一系列计算很有用-它允许在将特定结果标记为无效的同时继续进行计算。

一种变体是sNaN在每次操作后发出信号而不是保持安静。当无效结果需要中断计算以进行特殊处理时,这是一个有用的返回值。

当NaN涉及到a时,Python比较运算符的行为可能会有些令人惊讶 。其中一个操作数为安静或发信号的相等性测试NaN始终返回False(即使这样做 Decimal('NaN')==Decimal('NaN')),而不相等性的测试始终返回 True。尝试使用任何比较两个小数<, <=,>或>=运营商将抬高InvalidOperation如果操作数是一个信号NaN,并返回False如果这个信号没有被限制。请注意,“通用十进制算术”规范未指定直接比较的行为。这些涉及a的比较规则NaN取自IEEE 854标准(请参见5.7节中的表3)。为确保严格遵守标准,请使用compare() 和compare-signal()方法。

有符号的零可能来自下溢的计算。他们保留了如果以更高的精度进行计算会导致的结果。由于其大小为零,因此正零和负零均被视为相等,并且其符号具有参考意义。

除了两个不同但相等的有符号零外,还有各种表示形式的零,它们的精度不同,但值相等。这需要一点时间来适应。对于习惯于标准化浮点表示的眼睛而言,以下计算返回的值为零并不立即显而易见:

1 / Decimal('Infinity')
Decimal('0E-1000026')
使用线程
该getcontext()函数Context为每个线程访问一个不同的对象。具有独立的线程上下文意味着线程可以进行更改(例如getcontext().prec=10)而不会干扰其他线程。

同样,该setcontext()函数自动将其目标分配给当前线程。

如果setcontext()之前尚未调用过getcontext(), getcontext()则将自动创建一个新的上下文供当前线程使用。

新上下文是从称为DefaultContext的原型上下文中复制的。若要控制默认值,以便每个线程在整个应用程序中使用相同的值,请直接修改DefaultContext对象。这应该在启动任何线程之前完成 ,以免线程调用之间出现竞争状态getcontext()。例如:

# Set applicationwide defaults for all threads about to be launched
DefaultContext.prec = 12
DefaultContext.rounding = ROUND_DOWN
DefaultContext.traps = ExtendedContext.traps.copy()
DefaultContext.traps[InvalidOperation] = 1
setcontext(DefaultContext)

# Afterwards, the threads can be started
t1.start()
t2.start()
t3.start()
. . .
食谱
以下是一些用作实用程序功能的方法,并说明了使用Decimal该类的方法:

def moneyfmt(value, places=2, curr='', sep=',', dp='.',
             pos='', neg='-', trailneg=''):
    """Convert Decimal to a money formatted string.

    places:  required number of places after the decimal point
    curr:    optional currency symbol before the sign (may be blank)
    sep:     optional grouping separator (comma, period, space, or blank)
    dp:      decimal point indicator (comma or period)
             only specify as blank when places is zero
    pos:     optional sign for positive numbers: '+', space or blank
    neg:     optional sign for negative numbers: '-', '(', space or blank
    trailneg:optional trailing minus indicator:  '-', ')', space or blank

    >>> d = Decimal('-1234567.8901')
    >>> moneyfmt(d, curr='$')
    '-$1,234,567.89'
    >>> moneyfmt(d, places=0, sep='.', dp='', neg='', trailneg='-')
    '1.234.568-'
    >>> moneyfmt(d, curr='$', neg='(', trailneg=')')
    '($1,234,567.89)'
    >>> moneyfmt(Decimal(123456789), sep=' ')
    '123 456 789.00'
    >>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>')
    '<0.02>'

    """
    q = Decimal(10) ** -places      # 2 places --> '0.01'
    sign, digits, exp = value.quantize(q).as_tuple()
    result = []
    digits = list(map(str, digits))
    build, next = result.append, digits.pop
    if sign:
        build(trailneg)
    for i in range(places):
        build(next() if digits else '0')
    if places:
        build(dp)
    if not digits:
        build('0')
    i = 0
    while digits:
        build(next())
        i += 1
        if i == 3 and digits:
            i = 0
            build(sep)
    build(curr)
    build(neg if sign else pos)
    return ''.join(reversed(result))

def pi():
    """Compute Pi to the current precision.

    >>> print(pi())
    3.141592653589793238462643383

    """
    getcontext().prec += 2  # extra digits for intermediate steps
    three = Decimal(3)      # substitute "three=3.0" for regular floats
    lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
    while s != lasts:
        lasts = s
        n, na = n+na, na+8
        d, da = d+da, da+32
        t = (t * n) / d
        s += t
    getcontext().prec -= 2
    return +s               # unary plus applies the new precision

def exp(x):
    """Return e raised to the power of x.  Result type matches input type.

    >>> print(exp(Decimal(1)))
    2.718281828459045235360287471
    >>> print(exp(Decimal(2)))
    7.389056098930650227230427461
    >>> print(exp(2.0))
    7.38905609893
    >>> print(exp(2+0j))
    (7.38905609893+0j)

    """
    getcontext().prec += 2
    i, lasts, s, fact, num = 0, 0, 1, 1, 1
    while s != lasts:
        lasts = s
        i += 1
        fact *= i
        num *= x
        s += num / fact
    getcontext().prec -= 2
    return +s

def cos(x):
    """Return the cosine of x as measured in radians.

    The Taylor series approximation works best for a small value of x.
    For larger values, first compute x = x % (2 * pi).

    >>> print(cos(Decimal('0.5')))
    0.8775825618903727161162815826
    >>> print(cos(0.5))
    0.87758256189
    >>> print(cos(0.5+0j))
    (0.87758256189+0j)

    """
    getcontext().prec += 2
    i, lasts, s, fact, num, sign = 0, 0, 1, 1, 1, 1
    while s != lasts:
        lasts = s
        i += 2
        fact *= i * (i-1)
        num *= x * x
        sign *= -1
        s += num / fact * sign
    getcontext().prec -= 2
    return +s

def sin(x):
    """Return the sine of x as measured in radians.

    The Taylor series approximation works best for a small value of x.
    For larger values, first compute x = x % (2 * pi).

    >>> print(sin(Decimal('0.5')))
    0.4794255386042030002732879352
    >>> print(sin(0.5))
    0.479425538604
    >>> print(sin(0.5+0j))
    (0.479425538604+0j)

    """
    getcontext().prec += 2
    i, lasts, s, fact, num, sign = 1, 0, x, 1, x, 1
    while s != lasts:
        lasts = s
        i += 2
        fact *= i * (i-1)
        num *= x * x
        sign *= -1
        s += num / fact * sign
    getcontext().prec -= 2
    return +s
十进制常见问题解答
问:键入很麻烦decimal.Decimal('1234.5')。使用交互式解释器时,有没有一种方法可以减少打字?

答:一些用户将构造函数缩写为一个字母:

D = decimal.Decimal
D('1.23') + D('3.45')
Decimal('4.68')
问:在具有两位小数位的定点应用程序中,某些输入有很多位,需要四舍五入。其他人不应有多余的数字,需要进行验证。应该使用什么方法?

答:quantize()方法舍入到固定的小数位数。如果Inexact设置了陷阱,则对于验证也很有用:

TWOPLACES = Decimal(10) ** -2       # same as Decimal('0.01')
# Round to two places
Decimal('3.214').quantize(TWOPLACES)
Decimal('3.21')
# Validate that a number does not exceed two places
Decimal('3.21').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Decimal('3.21')
Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Traceback (most recent call last):
   ...
Inexact: None
问:一旦有了有效的两个位置输入,如何在整个应用程序中保持不变?

答:一些操作,例如加,减和乘以整数将自动保留定点。其他运算(例如除法和非整数乘法)将更改小数位数,并且需要执行以下quantize()步骤:

a = Decimal('102.72')           # Initial fixed-point values
b = Decimal('3.17')
a + b                           # Addition preserves fixed-point
Decimal('105.89')
a - b
Decimal('99.55')
a * 42                          # So does integer multiplication
Decimal('4314.24')
(a * b).quantize(TWOPLACES)     # Must quantize non-integer multiplication
Decimal('325.62')
(b / a).quantize(TWOPLACES)     # And quantize division
Decimal('0.03')
在开发定点应用程序时,定义用于处理该quantize()步骤的函数很方便:

def mul(x, y, fp=TWOPLACES):
    return (x * y).quantize(fp)
def div(x, y, fp=TWOPLACES):
    return (x / y).quantize(fp)
mul(a, b)                       # Automatically preserve fixed-point
Decimal('325.62')
div(b, a)
Decimal('0.03')
问:有很多表达相同价值的方法。这些数字200, 200.000,2E2,并且02E+4都在不同的精度相同的值。有没有办法将它们转换为单个可识别的规范值?

答:该normalize()方法将所有等效值映射到单个代表:

values = map(Decimal, '200 200.000 2E2 .02E+4'.split())
[v.normalize() for v in values]
[Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2')]
问:一些十进制值始终以指数表示法打印。有没有办法获得非指数表示形式?

答:对于某些值,指数表示法是表示系数中有效位数的唯一方法。例如,将表示 5.0E+3为5000可使值保持不变,但不能显示原件的两位数含义。

如果应用程序不关心跟踪重要性,则很容易删除指数和尾随零,从而失去重要性,但保持值不变:

def remove_exponent(d):
    return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
remove_exponent(Decimal('5E+3'))
Decimal('5000')
问:是否可以将常规浮点数转换为Decimal?

答:是的,尽管精确转换可能比直觉表明的精度更高,但是任何二进制浮点数都可以精确地表示为十进制。

>>> Decimal(math.pi)
Decimal('3.141592653589793115997963468544185161590576171875')
问:在复杂的计算中,如何确保由于精度不足或舍入异常而没有得到虚假结果。

答:十进制模块使测试结果变得容易。最佳实践是使用更高的精度和各种取整模式重新运行计算。差异很大的结果表明精度不足,舍入模式问题,输入条件不良或数值不稳定的算法。

问:我注意到上下文精度应用于运算结果,而不应用于输入。混合不同精度的值时需要注意什么吗?

答:是的。原理是所有值都被认为是精确的,这些值的算术也是如此。仅将结果四舍五入。输入的好处是“您输入的就是您得到的”。缺点是,如果您忘记了输入没有四舍五入的结果,结果可能看起来很奇怪:

>>> getcontext().prec = 3
>>> Decimal('3.104') + Decimal('2.104')
Decimal('5.21')
>>> Decimal('3.104') + Decimal('0.000') + Decimal('2.104')
Decimal('5.20')
解决方案是使用一元加号运算来提高精度或强制舍入输入:

>>> getcontext().prec = 3
>>> +Decimal('1.23456789')      # unary plus triggers rounding
Decimal('1.23')
或者,可以使用以下Context.create_decimal()方法在创建时对输入进行四舍五入 :

Context(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678')
Decimal('1.2345')
问:CPython实现是否可以快速用于大量应用?

答:是的。在CPython和PyPy3实现中,十进制模块的C / CFFI版本集成了高速libmpdec库,用于任意精度的正确舍入十进制浮点算法。 对中等大小的数字libmpdec使用Karatsuba乘法, 对非常大的数字使用数字理论变换。但是,要实现这种性能提升,需要为非四舍五入的计算设置上下文。

c = getcontext()
c.prec = MAX_PREC
c.Emax = MAX_EMAX
c.Emin = MIN_EMIN
版本3.3中的新功能。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 33 反对 0

使用道具 举报

发表于 2020-2-3 16:55:44 | 显示全部楼层
我要好好看文档
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-23 22:59:47 | 显示全部楼层
我要好好看文档
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-24 21:29:22 | 显示全部楼层
我要好好看文档
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-27 15:48:38 | 显示全部楼层
我要好好看文档
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-1 10:24:58 | 显示全部楼层
临时还看不懂decimal的一些东西
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-6 02:17:39 From FishC Mobile | 显示全部楼层
我真的不晓得我能不能学的会?真心看不懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2020-3-12 15:40:15 | 显示全部楼层
我要好好看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-13 21:04:46 | 显示全部楼层
我要好好看文档。
看不懂啊。。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2020-3-25 19:57:33 | 显示全部楼层
我要好好看文档
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-27 11:22

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表