python中decimal函数⽤法_decimal---⼗进制定点和浮点运算
伤感的图片
—Pytho。。。
Decimal 常见问题¶
Q. 总是输⼊ decimal.Decimal('1234.5') 是否过于笨拙。 在使⽤交互解释器时有没有最⼩化输⼊量的⽅式?
A. 有些⽤户会将构造器简写为⼀个字母:
>>>D = decimal.Decimal
>>>D('1.23') + D('3.45')
Decimal('4.68')
Q. 在带有两个⼗进制位的定点数应⽤中,有些输⼊值具有许多位,需要被舍⼊。 另⼀些数则不应具有多余位,需要验证有效性。 这种情况应该⽤什么⽅法?
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
Q. 当我使⽤两个有效位的输⼊时,我要如何在⼀个应⽤中保持有效位不变?
A. 某些运算例如与整数相加、相减和相乘将会⾃动保留固定的⼩数位数。 其他运算,例如相除和⾮整数相乘则将会改变⼩数位数,需要再加上 quantize() 处理步骤:
>>>a = Decimal('102.72') # Initial fixed-point values
>>>b = Decimal('3.17')
>>>a + b # Addition prerves 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 prerve fixed-point
Decimal('325.62')
>>>div(b, a)
Decimal('0.03')皮酒
Q. 表⽰同⼀个值有许多⽅式。 数字 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')]
Q. 有些⼗进制值总是被打印为指数表⽰形式。 是否有办法得到⼀个⾮指数表⽰形式?
A. 对于某些值来说,指数表⽰形式是表⽰系数中有效位的唯⼀办法。 例如,将 5.0E+3 表⽰为 5000 可以让值保持恒定,但是⽆法显⽰原本的两位有效数字。
如果⼀个应⽤不必关⼼追踪有效位,则可以很容易地移除指数和末尾的零,丢弃有效位但让值保持不变:
>>>def remove_exponent(d):
... return d.quantize(Decimal(1)) if d == d.to_integral() alize()
驴英语怎么说
>>>remove_exponent(Decimal('5E+3'))
Decimal('5000')
Q. 是否有办法将⼀个普通浮点数转换为 Decimal?
A. 是的,任何⼆进制浮点数都可以精确地表⽰为 Decimal 值,但完全精确的转换可能需要⽐平常感觉更⾼的精度:
>>>Decimal(math.pi)
Decimal('3.141592653589793115997963468544185161590576171875')
Q. 在⼀个复杂的计算中,我怎样才能保证不会得到由精度不⾜和舍⼊异常所导致的虚假结果。
A. 使⽤ decimal 模块可以很容易地检测结果。 最好的做法是使⽤更⾼的精度和不同的舍⼊模式重新进⾏计算。 明显不同的结果表明存在精度不⾜、舍⼊模式问题、不符合条件的输⼊或是结果不稳定的算
法。
Q. 我发现上下⽂精度的应⽤只针对运算结果⽽不针对输⼊。在混合使⽤不同精度的值时有什么需要注意的吗?
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(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678')
Decimal('1.2345')
Q. CPython 实现对于巨⼤数字是否⾜够快速?
A. 是的。 在 CPython 和 PyPy3 实现中,decimal 模块的 C/CFFI 版本集成了⾼速 libmpdec 库⽤于实现任意精度正确舍⼊的⼗进制浮点算术 1。 libmpdec 会对中等⼤⼩的数字使⽤ Karatsuba 乘法 ⽽对⾮常巨⼤的数字使⽤ 数字原理变换。
必须要对任意精度算术适配上下⽂。 Emin 和 Emax 应当总是设为最⼤值,clamp 应当总是设为 0 (默认值)。 设置 prec 需要⼗分谨慎。
进⾏⼤数字算术的最便捷⽅式也是使⽤ prec 的最⼤值 2:
>>>tcontext(Context(prec=MAX_PREC, Emax=MAX_EMAX, Emin=MIN_EMIN))
>>>x = Decimal(2) ** 256
>>>x / 128
Decimal('904625697166532776746648320380374280103671755200316906558262375061821325312')
民间歌曲
对于不精确的结果,在 64 位平台上 MAX_PREC 的值太⼤了,可⽤的内存将会不⾜:
>>>Decimal(1) / 3
Traceback (most recent call last):
File "", line 1, in
MemoryError
在具有超量分配的系统上 (即 Linux),⼀种更复杂的⽅式根据可⽤的 RAM ⼤⼩来调整 prec。 假设你有 8GB 的 RAM 并期望同时有 10个操作数,每个最多使⽤ 500MB:
>>>import sys
>>>
>>># Maximum number of digits for a single operand using 500MB in 8-byte words
>>># with 19 digits per word (4-byte and 9 digits for the 32-bit build):
>>>maxdigits = 19 * ((500 * 1024**2) // 8)
>>>
>>># Check that this works:
>>>c = Context(prec=maxdigits, Emax=MAX_EMAX, Emin=MIN_EMIN)
>>&aps[Inexact] = True
>>>tcontext(c)
>>>
>>># Fill the available precision with nines:
>>>x = Decimal(0).logical_invert() * 9
>>&sizeof(x)
524288112
>>>x + 2
父母的爱作文600字Traceback (most recent call last):
File "", line 1, in
decimal.Inexact: []
总体⽽⾔(特别是在没有超量分配的系统上),如果期望所有计算都是精确的则推荐预估更严格的边界并设置 Inexact 陷阱。
3.3 新版功能.
大雪节气的诗句在 3.9 版更改:此⽅式现在适⽤于除了⾮整数乘⽅以外的所有精确结果。