9.4. decimal十进制定点和浮点算术

V2.4 新增。

decimal模块为十进制浮点运算提供了支持。相比float数据类型,它有几个优势:

  • 十进制"是人想出来的一种浮点模式,因此必然有重要的指导原则 —— 对于在人们在学校学习的十进制算法,计算机也必须相同效果的算法" —— 摘自十进制算术规范。

  • 可以确切地表示十进制数。相比之下,类似1.12.2这种数字,并没有精确的二进制浮点数表示.最终用户通常不会指望1.1 + 2.2像作为二进制浮点数那样算出结果为3.3000000000000003

  • 精确的算法。在十进制浮点运算中,0.1 + 0.1 + 0.1 - 0.3正好等于零。在二进制浮点数,其结果是5.5511151231257827e-017虽然接近为零,差异防止可靠可以积累相等测试和差异。为此,十进制被首选会计应用程序有严格的平等不变量中。

  • 十进制模块涵盖重大地方概念1.30 + 1.202.50尾随零被保存下来,指示意义。这是习惯演示文稿中的货币的应用程序。用于乘法,"教科书"的办法使用所有数字中被乘数。例如, 1.3 * 1.21.56 1.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 类型公开只是一个温和的它的功能部分,十进制模块公开标准的所有必需的部件。当需要时,程序员有完全控制舍入和信号处理。这包括一个选项,以实施精确算法使用异常来阻止任何不精确的操作。

  • 十进制模块被为了支持"在不损害,都确切十进制算术 (有时称为定点算术) 以未经进位和舍入浮点算术。"— — 摘自十进制算术规范。

模块化的设计围绕着三个概念: 十进制数、 算术、 和信号的背景。

十进制数是永恒不变的。它有一个标志、 系数数字和指数。若要保留意义,系数数字不截断尾随零。小数也包括的特殊值有无穷大 -无穷远,和标准还区分-0+ 0

算术的上下文环境指定精度、 舍入规则,限制了指数,标志指示操作和陷阱的启用码,确定是否信号被视为例外的结果。舍入选项包括无穷方向 ROUND_DOWN无穷方向 ROUND_HALF_DOWN ROUND_HALF_EVEN ROUND_HALF_UP ROUND_UPROUND_05UP

信号是在计算的过程中所产生的特殊条件的组。根据应用程序的需要,信号可能会被忽略,被视为信息,或被视为异常。在十进制的模块中的信号是: Clamped DivisionByZero Inexact圆角迟缓溢出,和下溢

对于每个信号还有一个标志和一个陷阱启用码。遇到一个信号时,其国旗被设成 1,然后,如果陷阱启用设置为 1,则引发异常。旗帜是粘在一块儿,所以用户需要监视计算之前将它们重置。

请参见

9.4.1. Quick-start Tutorial

通常开始用小数时,先导入模块,用getcontext()查看当前上下文,如有必要,设置新值的精度,舍入,或启用陷阱:

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

>>> getcontext().prec = 7       # Set a new precision

十进制的实例可以由整数、 字符串、 浮点数或元组。从一个整数或浮点数建设执行精确的整数或浮点数的值转换。十进制数字包括的特殊值有非数值代表"不是数字",正和负无穷大,和-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.41421356237')
>>> Decimal(2) ** Decimal('0.5')
Decimal('1.414213562373095048801688724')
>>> Decimal('NaN')
Decimal('NaN')
>>> Decimal('-Infinity')
Decimal('-Infinity')

仅由数字输入的数量决定了一个新的小数的重要性。上下文精度和舍入在算术运算期间才开始发挥。

>>> 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')

小数也与很多其余的 Python 进行交互。这里是一个小的小数浮点飞行马戏团:

>>> data = 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)     # round() first converts to binary floating point
1.3
>>> int(a)
1
>>> a * 5
Decimal('6.70')
>>> a * b
Decimal('2.5058')
>>> c % a
Decimal('0.77')

一些数学函数,也可以为十进制表示形式:

>>> 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()函数。

按照这个标准,十进制的模块提供两个准备使用标准的情况下, BasicContextExtendedContext前者是特别有用的因为许多陷阱启用调试:

>>> 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=-999999999, Emax=999999999,
        capitals=1, 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=-999999999, Emax=999999999,
        capitals=1, flags=[Rounded, Inexact], 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

大多数程序在程序开始时只有一次,调整当前的上下文。而且,在许多应用中,数据在循环内部的单个演员转换为十进制上下文集与创建的小数位数,程序的大容量操作无异于与其他 Python 数值类型的数据。

9.4.2. Decimal objects

class decimal.Decimal([value[, context]])

构造新的十进制对象,从价值的基础。

可以是整数、 字符串、 元组、浮动十进制的另一个对象。如果未不指定任何,将返回Decimal('0')如果该值是一个字符串,它应符合十进制数字字符串语法中删除前导和尾随空白字符后:

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

如果该值是一个 unicode 字符串然后其他 Unicode 十进制数字也允许使用数字的上方。这些包括全形数字u '0' u '9'通过,其中从各种其他字母 (例如,阿拉伯-印度文、 天城的数字) 的小数位数。

如果元组,它应该有三个组件、 一个标志 (0为阳性) 或负1 元组的数字和整数指数。例如,十进制 ((0, (1, 4, 1, 4), -3))返回Decimal('1.414')

如果是一个浮点数,二进制浮点值是无损转换为等价的确切的十进制。这种转换可以经常要求 53 或更多位数的精度。例如, Decimal(float('1.1'))将转换为Decimal('1.100000000000000088817841970012523233890533447265625')

上下文精度并不影响存储多少位数。这完全取决中的数字个数。例如, Decimal('3.00000')即使上下文精度只有三个记录所有的五个零。

上下文参数的目的确定该怎么办如果该值是一个格式不正确的字符串。如果上下文捕获,则会引发异常 ;否则,该构造函数将返回新的十进制值为

一旦构造,十进制的对象是不可变的。

2.6 版本中的更改:前导和尾随空白字符允许从一个字符串创建一个十进制的实例时。

2.7 版本中的更改:现在允许构造函数的参数是浮法实例。

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

有一些小的差异之间十进制对象上的算法和算法对整数和浮点数。当余数运算符%应用于十进制的对象时,运算是结果的股息的标志,而不是结果的除数的符号:

>>> (-7) % 4
1
>>> Decimal(-7) % Decimal(4)
Decimal('-3')

整数除法运算符/ /表现类似地,而不其地板,以保持平常的身份返回 true 商数 (向零截断) 的整数部分x = = (x / / y) * y + x % y

>>> -7 // 4
-2
>>> Decimal(-7) // Decimal(4)
Decimal('-1')

%/ /运算符 (分别) 实施的其余部分鸿沟整数操作规范中所述。

十进制对象一般不与浮点数的算术运算组合: 试图添加十进制浮点数,例如,将提高TypeError还有这条规则的一个例外: 它是可以使用 Python 的比较运算符来比较浮法实例xy十进制的实例。这毫无例外,十进制浮动的实例之间的比较会遵循的一般规律为比较对象的表达式一节参考手册 》 中所描述的不同类型导致混乱的结果。

2.7 版本中的更改:浮法实例xy 十进制的实例之间的比较现在返回结果的基础的xy的值。在较早版本x < y返回任何十进制的实例xy任何浮法实例相同的 (任意) 结果。

除了标准的数字属性,十进制浮动点对象也有大量的专门的方法:

adjusted()

后移出系数的最右边的位数,直到只有铅数字仍然返回调整的指数: Decimal('321e+5').adjusted()返回七。用于确定最重要的位在小数点的位置。

as_tuple()

返回数名为元组表示: DecimalTuple (标志, 数字, 指数)

2.6 版本中的更改:使用指定的元组。

canonical()

返回参数的规范编码。目前,编码一个十进制是实例的总是规范,所以此操作返回其参数保持不变。

在 2.6 版本新。

compare(other[, context])

比较两个十进制实例的值。此操作的行为相同的方式通常比较方法__cmp__(),除了, compare()返回一个十进制的实例,而不是一个整数,如果任一操作数为 NaN 然后结果是 NaN:

a or b is a NaN ==> Decimal('NaN')
a < b           ==> Decimal('-1')
a == b          ==> Decimal('0')
a > b           ==> Decimal('1')
compare_signal(other[, context])

此操作是相同的compare()方法,除了所有 Nan 都信号。即是,如果操作数都不是信号的 NaN 任何安静的南操作数被视为就好像它是信号 NaN。

在 2.6 版本新。

compare_total(other)

比较两个操作数使用其抽象的表达,而不是他们的数值。类似于compare()方法,但结果给出了共订购十进制的实例上。两个十进制实例的数值相同但不同的表示形式与比较不等长的这种排序:

>>> Decimal('12.0').compare_total(Decimal('12'))
Decimal('-1')

安静和信号 Nan 也列入总体排序。此函数的结果是Decimal('0') ,如果两个操作数具有相同的表示形式, Decimal('-1') ,对于第一个操作数是否小于第二个和Decimal('1')订单总额如果第一个操作数是订单总额高于第二个操作数。请参见规范为总订单的详细信息。

在 2.6 版本新。

compare_total_mag(other)

比较两个操作数使用其抽象的表达,而不是他们的值,如compare_total(),但是忽略了每个操作数的符号。 x.compare_total_mag(y)等于x.copy_abs().compare_total(y.copy_abs())

在 2.6 版本新。

conjugate()

只是返回一个自我,这种方法只是遵守小数规范。

在 2.6 版本新。

copy_abs()

返回参数的绝对值。此操作不受上下文和安静: 无标志得到改变,并执行了没有舍入。

在 2.6 版本新。

copy_negate()

返回参数的否定。此操作不受上下文和安静: 无标志得到改变,并执行了没有舍入。

在 2.6 版本新。

copy_sign(other)

返回第一个操作数的副本,以符号设置为第二个操作数的符号相同。举个例子:

>>> Decimal('2.3').copy_sign(Decimal('-1.5'))
Decimal('-2.3')

此操作不受上下文和安静: 无标志得到改变,并执行了没有舍入。

在 2.6 版本新。

exp([context])

返回的值 (自然) 幂指函数e * * x在给定的数量。结果是正确四舍五入使用ROUND_HALF_EVEN舍入模式。

>>> Decimal(1).exp()
Decimal('2.718281828459045235360287471')
>>> Decimal(321).exp()
Decimal('2.561702493119680037517373933E+139')

在 2.6 版本新。

from_float(f)

将浮点数转换为一个十进制数,确切的调用。

注意Decimal.from_float(0.1)不是Decimal('0.1')相同。由于 0.1 是用二进制浮点数不精确表示,值存储为最近的是0x1.999999999999ap-4的可表示值。等值的十进制数是0.1000000000000000055511151231257827021181583404541015625

也可从 Python 2.7 起,直接从一个浮点数上构造一个十进制的实例。

>>> 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')

在 2.7 版本新。

fma(other, third[, context])

融合乘法-加法。回归自我 * 其他 + 第三没有舍入中间产品自我 * 其他。

>>> Decimal(2).fma(3, 5)
Decimal('11')

在 2.6 版本新。

is_canonical()

否则返回True如果参数是规范和虚伪目前,一个十进制的实例总是是规范的所以此操作总是返回True

在 2.6 版本新。

is_finite()

如果参数是一个有限的号码,和如果参数是无穷大或 NaN,则返回True

在 2.6 版本新。

is_infinite()

如果参数为正或负无穷大和虚假否则,返回True

在 2.6 版本新。

is_nan()

如果该参数是 (安静或信号) 南路和虚假否则,返回True

在 2.6 版本新。

is_normal()

如果参数是调整后的指数大于或等于额敏正常有限非零整数,则返回True 返回False如果参数是零,迟缓,无限或南。注意,术语的正常normalize ()方法用于创建规范值,这里在不同意义上使用。

在 2.6 版本新。

is_qnan()

如果参数是一个安静南路和虚假否则,返回True

在 2.6 版本新。

is_signed()

如果参数包含一个负号和虚假否则,返回True 请注意,零和 Nan 既能进行迹象。

在 2.6 版本新。

is_snan()

如果该参数是信号南路和虚假否则,返回True

在 2.6 版本新。

is_subnormal()

否则返回True如果参数是迟缓,和虚伪一个数字是低于正常如果它是零,有限的并得到调整后的指数小于额敏

在 2.6 版本新。

is_zero()

如果参数是一个 (正数或负数) 的零和虚假否则,返回True

在 2.6 版本新。

ln([context])

返回操作数的自然 (底为 e) 对数。结果是正确四舍五入使用ROUND_HALF_EVEN舍入模式。

在 2.6 版本新。

log10([context])

返回操作数的以 10 为底对数。结果是正确四舍五入使用ROUND_HALF_EVEN舍入模式。

在 2.6 版本新。

logb([context])

对于一个非零的数字,作为一个十进制的实例返回该运算符的操作数的调整的指数。如果操作数为零则返回Decimal('-Infinity')DivisionByZero国旗升起。如果操作数为无穷大然后返回Decimal('Infinity')

在 2.6 版本新。

logical_and(other[, context])

logical_and()是采用两个逻辑操作数的逻辑操作 (请参见逻辑操作数)。其结果是 digit-wise两个操作数。

在 2.6 版本新。

logical_invert([context])

logical_invert()是一个逻辑的操作。其结果是操作数的 digit-wise 反演。

在 2.6 版本新。

logical_or(other[, context])

logical_or()是采用两个逻辑操作数的逻辑操作 (请参见逻辑操作数)。其结果是 digit-wise两个操作数。

在 2.6 版本新。

logical_xor(other[, context])

logical_xor()是采用两个逻辑操作数的逻辑操作 (请参见逻辑操作数)。其结果是 digit-wise 独家或两个操作数。

在 2.6 版本新。

max(other[, context])

最大 (自我, 其他)只是舍入规则的上下文应用在返回之前和NaN值终止或忽略 (具体取决于上下文和它们发出的信号还是安静的)。

max_mag(other[, context])

做了类似的max ()方法,但比较使用绝对值的操作数。

在 2.6 版本新。

min(other[, context])

min (自我, 其他)只是舍入规则的上下文应用在返回之前和NaN值终止或忽略 (具体取决于上下文和它们发出的信号还是安静的)。

min_mag(other[, context])

做了类似的min ()方法,但比较使用绝对值的操作数。

在 2.6 版本新。

next_minus([context])

返回的最大的数可以表示在给定的上下文中 (或在假如没有上下文的当前线程上下文中),这是小于给定的操作数。

在 2.6 版本新。

next_plus([context])

返回最小的数可以表示在给定的上下文中 (或在假如没有上下文的当前线程上下文中),这是大于给定的操作数。

在 2.6 版本新。

next_toward(other[, context])

如果两个操作数相等,返回数的第二个操作数的方向接近第一个操作数。如果两个操作数的数值相等,返回第一个操作数的副本,以符号设置为第二个操作数的符号相同。

在 2.6 版本新。

normalize([context])

通过剥离的最右边的尾随零,并将任何结果平等转换为Decimal('0')Decimal('0e0')规范数量。用于生产规范的等价类的属性值。例如, Decimal('32.100')Decimal('0.321000e+2')这两个规范Decimal('32.1')的等效值。

number_class([context])

返回一个字符串,描述的操作数。返回的值是以下十个字符串之一。

  • "-Infinity", indicating that the operand is negative infinity.
  • "-Normal", indicating that the operand is a negative normal number.
  • "-Subnormal", indicating that the operand is negative and subnormal.
  • "-Zero", indicating that the operand is a negative zero.
  • "+Zero", indicating that the operand is a positive zero.
  • "+Subnormal", indicating that the operand is positive and subnormal.
  • "+Normal", indicating that the operand is a positive normal number.
  • "+Infinity", indicating that the operand is positive infinity.
  • "NaN", indicating that the operand is a quiet NaN (Not a Number).
  • "sNaN", indicating that the operand is a signaling NaN.

在 2.6 版本新。

quantize(exp[, rounding[, context[, watchexp]]])

舍入,第二个操作数的指数之后,返回一个值等于第一个操作数。

>>> Decimal('1.41421356').quantize(Decimal('1.000'))
Decimal('1.414')

不同于其他的行动,如果的系数量化后术后的长度将大于精度,然后为终止。这可以保证除非有一个错误条件,量化的指数是总是等于右边的操作数。

也不同于其他行动量化从来没有信号下溢,即使结果是迟缓和不精确。

指数的第二个操作数是否大于第一次然后四舍五入的可能是必要的。在这种情况下,舍入模式决定由舍入的参数,如果给出,否则由给定的上下文参数 ;如果参数都不给出了舍入使用当前线程上下文模式。

如果将watchexp设置 (默认值),然后生成指数时比Emax大于或小于Etiny返回错误。

radix()

返回Decimal(10),基数 (基础)十进制类做它的算法。包括与规格的兼容性。

在 2.6 版本新。

remainder_near(other[, context])

从除以自我其他返回余数。这不同于自我 % 其他在这剩下的人的标志选择,尽量减少其绝对值。更确切地说,返回的值是 - n * 其他在那里n自我 / 其他的确切值最接近的整数,如果两个整数同样附近然后甚至一选择。

如果结果为零,然后其符号将会被自我的标志。

>>> 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(other[, context])

返回的结果的旋转对于第一个操作数的位数由第二个操作数指定的数量。第二个操作数必须是一个整数范围中的 — — 经过精密精度。第二个操作数的绝对价值给出的数旋转的地方。如果第二个操作数是积极然后旋转是向左 ;否则旋转是向右。对于第一个操作数的系数在左边用零长度的精度,如有必要填充。标志和指数的第一个操作数是保持不变。

在 2.6 版本新。

same_quantum(other[, context])

测试是否自我和其他有相同的指数或是否都是NaN

scaleb(other[, context])

与指数调整的第二个返回第一个操作数。等价的说,返回第一个操作数乘以10 * * 其他第二个操作数必须是一个整数。

在 2.6 版本新。

shift(other[, context])

返回由第二个操作数指定数量的转移的第一个操作数的有效数字的结果。第二个操作数必须是一个整数范围中的 — — 经过精密精度。第二个操作数的绝对值给出的数转移的地方。如果第二个操作数是积极转变则向左 ;否则这种转变是向右。转移入系数的数字是零。标志和指数的第一个操作数是保持不变。

在 2.6 版本新。

sqrt([context])

返回到完全精度参数的平方根。

to_eng_string([context])

将转换为字符串的工程类型。

工程符号具有指数这是 3 的倍数,所以有高达 3 位数左边的小数位。例如,将Decimal('123E+1')转换为Decimal('1.23E+3')

to_integral([rounding[, context]])

to_integral_value()方法相同。 To_integral的名字一直与旧版本兼容性。

to_integral_exact([rounding[, context]])

舍入到最接近的整数,信号Inexact圆角酌情如果舍入发生。舍入模式是由的舍入的参数,如果给出,否则由给定的上下文确定的。如果没有参数给出了然后舍入使用当前上下文的模式。

在 2.6 版本新。

to_integral_value([rounding[, context]])

没有显示信号Inexact圆角,舍入到最接近的整数。如果给定,适用舍入否则,将使用提供的上下文或当前上下文中的舍入方法。

2.6 版本中的更改: to_integral由重命名为to_integral_value旧名称仍然是有效的兼容性。

9.4.2.1. Logical operands

Logical_and() logical_invert() logical_or()logical_xor()方法期望他们的论点是逻辑操作数一个逻辑的操作数是一个十进制的实例,其指数和标志是均为零,和其位数都是01

9.4.3. Context objects

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

每个线程具有自己当前的上下文,这访问或更改使用getcontext()setcontext()函数:

decimal.getcontext()

返回活动线程的当前上下文。

decimal.setcontext(c)

将活动线程的当前上下文设置为c

开头 Python 2.5,您还可以使用with语句和localcontext()功能若要暂时更改活动上下文。

decimal.localcontext([c])

返回上下文管理器会将活动线程的当前上下文设置为c的复印件在 with 语句进入和退出 with 语句时恢复以前的上下文。如果指定了没有上下文,则使用当前上下文的副本。

新版本 2.5 中的。

例如,下面的代码将当前的小数精度设置为 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

with localcontext(BasicContext):      # temporarily use the BasicContext
    print Decimal(1) / Decimal(7)
    print Decimal(355) / Decimal(113)

也可以使用如下所述的情况下构造函数创建新的上下文。此外,该模块提供了三种预制的上下文:

class decimal.BasicContext

这是由一般的十进制算术规范定义的标准上下文。精度设置为 9 个。舍入将设置为ROUND_HALF_UP所有的标志都被清除。所有的陷阱被启用 (被视为例外) 除了Inexact圆角,和迟缓

因为很多陷阱被启用,这种情况下对于调试很有用。

class decimal.ExtendedContext

这是由一般的十进制算术规范定义的标准上下文。精度设置为 9 个。舍入将设置为ROUND_HALF_EVEN所有的标志都被清除。没有陷阱被启用 (以便在计算过程中不引发异常)。

因为陷阱被禁用,这种情况下是对于宁愿要的NaN无穷大的结果值,而不是引发异常的应用程序有用。这允许应用程序以完成条件,否则将阻止该程序在运行。

class decimal.DefaultContext

这种情况下用作上下文构造函数原型新的上下文。更改字段 (精度) 已更改为新的上下文,该上下文构造函数创建的默认的效果。

这种情况下是在多线程环境中最有用的。改变的领域之一,在启动线程之前已设置系统范围的默认值的效果。建议不要更改字段后线程已经开始,因为这需要线程同步以避免争用条件。

在单线程环境中,它是最好不使用此上下文。相反,只需创建上下文明确如下所述。

默认值精度 = 28,舍入 = ROUND_HALF_EVEN,并启用溢出、 此,和 DivisionByZero 的陷阱。

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

class decimal.Context(prec=None, rounding=None, traps=None, flags=None, Emin=None, Emax=None, capitals=1)

创建一个新的上下文。如果一个字段未指定或没有,从DefaultContext复制的默认值。如果标志字段未指定或没有,所有的标志都被清除。

Prec字段是一个正整数,设置上下文中的算术运算的精度。

舍入选项之一:

  • ROUND_CEILING (towards Infinity),
  • ROUND_DOWN (towards zero),
  • ROUND_FLOOR (towards -Infinity),
  • ROUND_HALF_DOWN (to nearest with ties going towards zero),
  • ROUND_HALF_EVEN (to nearest with ties going to nearest even integer),
  • ROUND_HALF_UP (to nearest with ties going away from zero), or
  • ROUND_UP (away from zero).
  • ROUND_05UP (away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise towards zero)

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

额敏Emax字段是指定允许的外部界限为指数的整数。

首都字段是01 (默认值)。如果设置为1,指数都印有资本E否则,使用小写e Decimal('6.02e+23')

2.6 版本中的更改:添加了ROUND_05UP舍入模式。

上下文类定义通用的几种方法,以及一大批做直接在给定的上下文中的算术方法。此外,每个上面有描述 (不包括adjusted()as_tuple()的方法) 的十进制方法是相应的上下文方法。例如,对于一个上下文实例C十进制实例x C.exp(x)是相当于x.exp(context=C)每个上下文方法接受一个 Python 整数 (实例int的) 任何地方,接受了一个十进制的实例。

clear_flags()

将重置所有标记为0

copy()

返回上下文的副本。

copy_decimal(num)

返回十进制的实例数量的副本

create_decimal(num)

创建一个新的十进制实例从num但使用自我作为上下文。十进制的构造函数中,不同上下文的精度,舍入方法,标记,并将陷阱应用于转换。

这是有用的因为常量通常发放给不是由应用程序需要更高的精度。另一个好处是舍入立即消除无意造成的影响,从超出当前的精度位数。在以下示例中,使用以未经进位的投入意味着添加零到一笔可以改变的结果:

>>> 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)

从浮f但舍入使用自我作为上下文创建一个新的十进制实例。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):
    ...
Inexact: None

在 2.7 版本新。

Etiny()

返回一个值等于额敏 - prec + 1是最小的指数值低于正常的结果。下溢时,指数被设置为Etiny

Etop()

返回一个值等于Emax - prec + 1

致力于与小数常用的方法是创建十进制的实例,然后应用发生在活动的线程的当前上下文内的算术运算。一种替代方法是使用上下文方法计算某特定上下文内。方法类似于十进制的等级,在这里只简述。

abs(x)

返回x的绝对值。

add(x, y)

返回xy的总和。

canonical(x)

返回相同的十进制对象x

compare(x, y)

Xy进行了数值比较。

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

is_nan(x)

返回True ,如果x是一个 qNaN 或懒汉 ;否则返回False

is_normal(x)

返回True如果x是一个正常的数字 ;否则返回False

is_qnan(x)

返回True如果x是安静的南 ;否则返回False

is_signed(x)

返回True如果x为负值 ;否则返回False

is_snan(x)

返回True如果x是信号的南 ;否则返回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)

适用于逻辑运算xor之间每个操作数的位数。

max(x, y)

进行了数值比较两个值,并返回最大值。

max_mag(x, y)

他们忽略的标志与数值比较的值。

min(x, y)

进行了数值比较两个值,并返回最小值。

min_mag(x, y)

他们忽略的标志与数值比较的值。

minus(x)

减去对应一元前缀运算符在 Python 中减去。

multiply(x, y)

返回xy的乘积。

next_minus(x)

返回的最大的能上演的数目小于x

next_plus(x)

返回最小的能上演数大于x

next_toward(x, y)

返回数接近xy方向。

normalize(x)

降低x到最简单的形式。

number_class(x)

返回x类的指示。

plus(x)

再加上对应于一元前缀加在 Python 中的运算符。此操作适用于上下文精度和舍入,所以它是标识操作。

power(x, y[, modulo])

返回xy,如果给出了减少的权力。

带有两个参数,计算x * * y如果x是负y必须为整数。除非是不可或缺的y和结果是有限的而且可以完全用 '精度' 数字表示,结果将是不精确。结果应总是正确地舍入,使用当前线程上下文的舍入模式。

具有三个参数,计算(x * y) % 对于三个参数窗体中,参数的以下限制持有:

  • all three arguments must be integral
  • y must be nonnegative
  • at least one of x or y must be nonzero
  • modulo must be nonzero and have at most ‘precision’ digits

所产生的值Context.power (x, y, 模)等于将通过计算得到的值(x * * y) % 以无界的精度,但更有效地进行计算。指数的结果为零,无论x y指数。结果始终是确切的。

2.6 版本中的更改: y现在可能在非整型x * * y三个参数的版本更严格的要求。

quantize(x, y)

返回一个值相等于x (四舍五入), y的指数。

radix()

只是返回 10,因为这是十进制数字,:)

remainder(x, y)

返回从整数除法的余数。

结果,标志如果非零,是股利的原始相同。

remainder_near(x, y)

返回x - y * n,其中n是最近的x / y的确切值的整数 (如果结果为 0,那么它的标志将是x的标志)。

rotate(x, y)

返回旋转的副本的xy时代。

same_quantum(x, y)

如果两个操作数具有相同的指数,则返回True

scaleb(x, y)

返回第一个操作数添加第二个值后其进出口。

shift(x, y)

返回转移的副本的xy时代。

sqrt(x)

对上下文精度的非负数的平方根。

subtract(x, y)

返回xy之间的区别。

to_eng_string(x)

将数字转换为字符串,使用科学记数法。

to_integral_exact(x)

舍入为整数。

to_sci_string(x)

将数字转换为字符串使用科学记数法。

9.4.4. Signals

信号表示在计算过程中出现的条件。每个对应一个上下文国旗和一个上下文陷阱的启用码。

每当遇到的情况,就是设置上下文标志。经计算,可检查标志仅供参考之用 (例如,以确定计算是否准确)。在检查后的标志,一定要在开始下一次计算之前清除所有标志。

如果上下文的陷阱启用码设置的信号,然后条件的原因都会引发 Python 异常。例如,如果设置了DivisionByZero陷阱,然后DivisionByZero引发一个异常是遇到条件后。

class decimal.Clamped

改变指数以适合表示形式的限制。

当指数下跌上下文的额敏Emax范围以外,通常情况下,夹紧时发生。如果可能的话,指数被缩小以适合通过添加零系数。

class decimal.DecimalException

其他的信号和ArithmeticError的一个子类的基类。

class decimal.DivisionByZero

通过零信号非无限数量的分工。

会发生分裂,余数,或者当一个否定的权力对某个数字。如果这个信号不被困住,返回无穷大-无穷大与标志由计算的输入。

class decimal.Inexact

指示舍入发生并且是不够确切的结果。

当非零数字被丢弃在舍入过程中的信号。返回舍入的结果。信号旗或陷阱用来检测时结果不精确。

class decimal.InvalidOperation

执行无效的操作。

指示被请求的操作,那没有任何意义。如果不困,返回NaN可能的原因包括:

Infinity - Infinity
0 * Infinity
Infinity / Infinity
x % 0
Infinity % x
x._rescale( non-integer )
sqrt(-x) and x > 0
0 ** 0
x ** (non-integer)
x ** Infinity
class decimal.Overflow

数值溢出。

指示指数大于Emax舍入发生后。如果不困,结果取决于舍入模式,或拉抵港的最大的能上演有限数量,向外四舍五入到无穷大在任一情况下,也标志着Inexact圆角

class decimal.Rounded

舍入发生虽然可能丢失了没有信息。

暗示只要舍入数字抛弃物 ;即使这些数字为零 (例如,舍入5.005.0)。如果不困,返回的结果不变。这种信号用于检测的有效位数的损失。

class decimal.Subnormal

指数低于额敏前舍入。

操作结果时发生异常低压 (指数是太小了)。如果不困,返回的结果不变。

class decimal.Underflow

数值的暗流与结果舍入到零。

低于正常的结果推送到零舍入时发生。也标志着Inexact迟缓

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

exceptions.ArithmeticError(exceptions.StandardError)
    DecimalException
        Clamped
        DivisionByZero(DecimalException, exceptions.ZeroDivisionError)
        Inexact
            Overflow(Inexact, Rounded)
            Underflow(Inexact, Rounded, Subnormal)
        InvalidOperation
        Rounded
        Subnormal

9.4.5. Floating Point Notes

9.4.5.1. Mitigating round-off error with increased precision

采用十进制浮点数,消除的十进制表示形式错误 (使其可以精确表示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')

十进制的模块使得能够恢复身份通过扩展精度足以避免损失的意义:

>>> 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')

9.4.5.2. Special values

数字系统为十进制模块提供特殊值包括教授膏方进补 -无穷远无穷大和两个零, + 0-0

无穷大可以直接与构造: Decimal('Infinity')此外,他们可以产生从除以零,当DivisionByZero信号不被困。同样地,当溢出信号不被困住,无限可能起因于界限能上演人数最多的舍入。

无穷大签署 (仿射) 和可以用于算术运算在那里,得到把它们看成是非常大的不确定的数字。例如,将一个常数添加到无穷大给另一种无限的结果。

某些操作是不确定的和返回,或如果信号被困住,引发的异常。例如, 0/0返回这就意味着"不是数字"。这种品种的是安静,一旦创建,将流过总是导致另一个其他计算。此行为可用于一系列计算,偶尔会有失踪的投入 — — 它允许计算继续同时标记为无效的具体结果。

Variant 是懒汉信号而不是剩余安静后的每个操作。这是一个有用的返回值时无效的结果需要中断计算进行特殊处理。

涉及,Python 的比较运算符的行为可以是有点令人惊讶。测试相等性在其中一个操作数是一个安静或信号总是返回(即使做Decimal('NaN')==Decimal('NaN')),而不等式测试总是返回True尝试比较两个小数位数,使用任何< < = >> =运算符将提高信号,如果任何一个操作数为,并返回False ,如果这种信号不被困。请注意一般十进制算术规范没有指定的行为进行直接的比较 ;这些规则,以便比较涉及取自 IEEE 854 标准 (见表 3 中 5.7 节)。为了确保严格的标准,请使用compare()compare-signal()的方法。

签名的零导致计算的暗流。他们保持迹象表明将会造成如果到更高的精度进行了计算。由于他们的规模是零,积极和消极的零被视为平等,他们的标志是提供信息。

除了尚是截然不同的两个签名零平等,还有零与不同精度的各种表示形式尚未价值相等的。这需要一点时间来适应。习惯了归一化浮动点表示法眼,并非立即明显以下的计算方法会返回一个值等于零:

>>> 1 / Decimal('Infinity')
Decimal('0E-1000000026')

9.4.6. Working with threads

Getcontext()函数访问一个不同的上下文对象,每个线程。而不会干扰其他线程具有单独的线程上下文中意味着线程可能做出的更改 (例如getcontext.prec=10)。

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

如果不前,该署在getcontext()之前,调用setcontext() ,然后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()
 . . .

9.4.7. Recipes

在这里是作为效用函数的几个食谱,并证明如何工作与十进制的类:

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 = map(str, digits)
    build, next = result.append, digits.pop
    if sign:
        build(trailneg)
    for i in range(places):
        build(next() if digits else '0')
    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.

    >>> 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.

    >>> 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

9.4.8. Decimal FAQ

问: 它是繁琐为十进制的类型。Decimal('1234.5')。有没有办法尽量减少打字时使用交互式解释器吗?

A.某些用户使用缩写的构造函数只是单一的信:

>>> D = decimal.Decimal
>>> D('1.23') + D('3.45')
Decimal('4.68')

问: 在带有两位小数的定点应用中,一些投入有很多地方和需要舍入。其他人不应该有多余的数字,需要进行验证。应该用什么方式呢?

A. 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

问: 一旦我有有效的两个地方输入,如何维护,整个应用程序不变?

A.某些操作,如加法、 减法和乘法一个整数,将自动保留不动点。其他操作如,司和非整数乘法,将更改的小数位数,需要被追踪了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所有在不同精度具有相同的值。有什么办法,将它们转换为一个单一的可识别规范的值吗?

A. 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')]

问: 一些十进制值始终打印与指数记数法。有一个办法让非指数表示法吗?

A.对于某些值,指数记数法是唯一能表达系数显著学额的数目。例如,表示5.0E + 35000恒定值,但无法显示原始的两个地方的意义。

如果应用程序不关心跟踪意义,很容易删除的指数和尾随的零,失去意义,但保留的值保持不变:

def remove_exponent(d):
    '''Remove exponent and trailing zeros.

    >>> remove_exponent(Decimal('5E+3'))
    Decimal('5000')

    '''
    return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()

问: 有没有办法将转换为十进制的普通浮法吗?

答: 是的任何二进制浮点数可以确切地表示一个十进制数虽然确切的转换可能需要更高的精度比直觉会显示:

>>> Decimal(math.pi)
Decimal('3.141592653589793115997963468544185161590576171875')

问: 在一个复杂的计算,我怎样才能确保我没有因为精度不够高或舍入异常得到虚假的结果。

A.十进制的模块,便于测试结果。最佳做法是使用更精确的重新运行计算,各种的舍入模式。广泛不同结果表明精度不够高、 舍入模式问题、 病态的投入或数值不稳定的算法。

问: 我注意到上下文精度应用操作的结果,而不是投入。有什么事情要提防混合精度不同值时的吗?

A.是。这个原则是,认为所有值都要准确,因此是对这些值的算术。只有结果将四舍五入。投入的优势是您键入的内容是"你得到了什么"。结果可以看起来很奇怪,如果你忘记了投入还没有被磨圆的一个缺点是:

>>> 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')