从float文字构造时奇怪的十进制行为

时间:2015-08-24 19:01:05

标签: python decimal

我期待2小数精确,但是:

>>> from decimal import Decimal, getcontext
>>> getcontext().prec = 2
>>> Decimal(98791.4913)
Decimal('98791.491299999994225800037384033203125')
>>> getcontext()
Context(prec=2, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])

为什么Decimal不尊重Context精确度?

2 个答案:

答案 0 :(得分:4)

引自documentation(强调我的) -

  

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

     

上下文精度不会影响存储的位数。这完全由值的位数决定。例如,即使上下文精度仅为3,Decimal('3.00000')也会记录所有五个零。

     

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

from same documentation -

  

新十进制的重要性仅由输入的位数决定。上下文精度和舍入仅在算术运算期间发挥作用。

文档中给出了很好的例子 -

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

答案 1 :(得分:2)

来自documentation

  

如果 value 是一个浮点数,则二进制浮点值是无损的   转换为精确的十进制等值。 此转换通常可以   需要53位或更多精度。例如,   Decimal(float('1.1'))转换为   Decimal('1.100000000000000088817841970012523233890533447265625')

     

上下文精度不会影响存储的位数。那   仅由值中的位数确定。

     

...

     

上下文精度和舍入仅在算术运算期间发挥作用。

强调我的。

您可以使用Decimal.quantize方法截断该值:

places = 2
Decimal(98791.4913).quantize(Decimal(10) ** -places) # 98791.49

Context.quantize

places = 2
getcontext().quantize(Decimal(98791.4913), Decimal(10) ** -places) # 98791.49