十进制固定精度

时间:2019-07-02 07:53:52

标签: python decimal currency

我想在货币计算中使用小数,因此我想对逗号后面的两个数字进行精确运算。最初,我认为十进制上下文中的prec是指该属性,但是经过几次实验,我感到有些困惑。

实验1:

In [1]: import decimal                                                                                                                      

In [2]: decimal.getcontext().prec = 2                                                                                                       

In [3]: a = decimal.Decimal('159.9')                                                                                                        

In [4]: a                                                                                                                                   
Out[4]: Decimal('159.9')

In [5]: b = decimal.Decimal('200')                                                                                                          

In [6]: b                                                                                                                                   
Out[6]: Decimal('200')

In [7]: b - a                                                                                                                               
Out[7]: Decimal('40')

实验2:

In [8]: decimal.getcontext().prec = 4                                                                                                       

In [9]: a = decimal.Decimal('159.9')                                                                                                        

In [10]: a                                                                                                                                  
Out[10]: Decimal('159.9')

In [11]: b = decimal.Decimal('200')                                                                                                         

In [12]: b                                                                                                                                  
Out[12]: Decimal('200')

In [13]: b - a                                                                                                                              
Out[13]: Decimal('40.1')

实验3:prec仍设置为4)

In [14]: a = decimal.Decimal('159999.9')                                                                                                    

In [15]: a                                                                                                                                  
Out[15]: Decimal('159999.9')

In [16]: b = decimal.Decimal('200000')                                                                                                      

In [17]: b                                                                                                                                  
Out[17]: Decimal('200000')

In [18]: b - a                                                                                                                              
Out[18]: Decimal('4.000E+4')

为什么它在我的示例中起作用?在(货币计算)情况下,应该如何使用小数?

2 个答案:

答案 0 :(得分:1)

精度设置的有效位数,不等于小数点后的位数。

因此,如果精度为2,则将有两个有效数字,因此具有3个有效数字的数字(如40.1将被减少为前两个有效数字,得到40。 / p>

没有简单的方法用Decimal设置小数点后的位数。但是,您可以使用高精度,并且始终将结果round保留为两位小数:

>>> from decimal import Decimal, getcontext
>>> getcontext().prec = 60  # use a higher/lower one if needed
>>> Decimal('200') - Decimal('159.9')
Decimal('40.1')
>>> r = Decimal('200') - Decimal('159.9')
>>> round(r, 2)
Decimal('40.10')

decimal FAQ还包含类似的问答(使用quantize):

  问:在具有两位小数位的定点应用程序中,某些输入有很多位,需要四舍五入。其他人不应有多余的数字,需要进行验证。应该使用什么方法?

     

A。 Quantize()方法将舍入到固定数量的小数位数。如果设置了不精确陷阱,则它对于验证也很有用:

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

答案 1 :(得分:1)

我发现最好的方法是设置较高的prec并使用Decimal.quantize来取整结果:

decimal.getcontext().prec=100
a = Decimal('400000.123456789')
b = Decimal('200000.0')
a-b
>>> Decimal('2.0000E+5')
(a-b).quantize(Decimal('0.01'))
>>> Decimal('200000.12')