从浮点文字构造时出现奇怪的十进制行为
Strange Decimal behavior while constructing from float literal
我期望 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
精度?
引用自documentation(强调我的)-
If value is a float, the binary floating point value is losslessly converted to its exact decimal equivalent. This conversion can often require 53 or more digits of precision. For example, Decimal(float('1.1')) converts to Decimal('1.100000000000000088817841970012523233890533447265625').
The context precision does not affect how many digits are stored. That is determined exclusively by the number of digits in value. For example, Decimal('3.00000') records all five zeros even if the context precision is only three.
The purpose of the context argument is determining what to do if value is a malformed string. If the context traps InvalidOperation, an exception is raised; otherwise, the constructor returns a new Decimal with the value of NaN.
The significance of a new Decimal is determined solely by the number of digits input. Context precision and rounding only come into play during arithmetic operations.
文档中给出了很好的例子 -
>>> 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')
If value is a float, the binary floating point value is losslessly
converted to its exact decimal equivalent. This conversion can often
require 53 or more digits of precision. For example,
Decimal(float('1.1'))
converts to
Decimal('1.100000000000000088817841970012523233890533447265625')
.
The context precision does not affect how many digits are stored. That
is determined exclusively by the number of digits in value.
...
Context precision and rounding only come into play during arithmetic operations.
强调我的。
您可以使用 Decimal.quantize
方法截断该值:
places = 2
Decimal(98791.4913).quantize(Decimal(10) ** -places) # 98791.49
places = 2
getcontext().quantize(Decimal(98791.4913), Decimal(10) ** -places) # 98791.49
我期望 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
精度?
引用自documentation(强调我的)-
If value is a float, the binary floating point value is losslessly converted to its exact decimal equivalent. This conversion can often require 53 or more digits of precision. For example, Decimal(float('1.1')) converts to Decimal('1.100000000000000088817841970012523233890533447265625').
The context precision does not affect how many digits are stored. That is determined exclusively by the number of digits in value. For example, Decimal('3.00000') records all five zeros even if the context precision is only three.
The purpose of the context argument is determining what to do if value is a malformed string. If the context traps InvalidOperation, an exception is raised; otherwise, the constructor returns a new Decimal with the value of NaN.
The significance of a new Decimal is determined solely by the number of digits input. Context precision and rounding only come into play during arithmetic operations.
文档中给出了很好的例子 -
>>> 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')
If value is a float, the binary floating point value is losslessly converted to its exact decimal equivalent. This conversion can often require 53 or more digits of precision. For example,
Decimal(float('1.1'))
converts toDecimal('1.100000000000000088817841970012523233890533447265625')
.The context precision does not affect how many digits are stored. That is determined exclusively by the number of digits in value.
...
Context precision and rounding only come into play during arithmetic operations.
强调我的。
您可以使用 Decimal.quantize
方法截断该值:
places = 2
Decimal(98791.4913).quantize(Decimal(10) ** -places) # 98791.49
places = 2
getcontext().quantize(Decimal(98791.4913), Decimal(10) ** -places) # 98791.49