python精确计算包decimal,告别截断误差

本文已整合到这里:Python内置数学模块全整理,易查易阅

在python中比较常见的问题是

>>> 0.333333333333333333333*3
1.0
>>> 0.999999999999999999999999
1.0

如果这可以算作程序的“自作聪明”的话,那么下面这个就是完全没有必要的误差了。

>>> 0.1*3-0.3
5.551115123125783e-17

decimal就为了解决这个问题,下面的代码默认from decimal imoprt *

通过Decimal来新建一个Decimal格式的数字,然后就可以像float一样使用Python中的函数了。

>>> x = Decimal(1)
>>> x
Decimal('1')
>>> x/3
Decimal('0.3333333333333333333333333333')
>>> x/3*3
Decimal('0.9999999999999999999999999999')

Decimal对象

Decimal中内置了很多函数,可以通过如下形式调用

>>> D = decimal.Decimal
>>> x = D(15)
>>> x.sqrt()
Decimal('3.872983346207416885179265400')

此外,可以输入一些字符串来得到特殊值,例如无穷大

>>> x = D('Infinity')
>>> x
Decimal('Infinity')
成员变量imagreal
虚部实部
函数
返回自身conjugatecanonicalnormalize返回最简形式,number_class返回类形式
用于判断is_finite, is_infinite, is_zero, is_signed(判断正数),
is_nan, is_qnan, is_snan
is_normal, is_subnormal, is_canonical,
数学函数exp, ln, log10, logb, sqrtcopy_abscopy_negate返回负值
舍入函数to_integral_exactto_integral_value, to_integral
转字符串to_eng_string转字符串,as_tuple 返回每一位数字的元组
返回分数as_integer_ratio= a b \frac{a}{b} ba
移位函数adjusted 返回科学计数法的指数
相邻数字next_minusnext_plus
双元运算,默认格式为a.xxx(b)
常规运算remainder_near求余,quantize 乘方,a.scaleb(b)= a × 1 0 b a\times10^b a×10b
逻辑运算logical_and, logical_invert, logical_or, logical_xor
比较运算compare 相等为0,a>b为1,a< b为-1
compare_signalcompare_totalcompare_total_mag
a.copy_sign(b)= ∣ b ∣ b a \frac{|b|}{b}a bba
same_quantum如有相同指数则返回1
相邻值next_toward返回趋向b的最接近于a的数字
最值max, min, max_mag, min_mag, 例如a.max(b)等价于max(a,b)

常量和成员变量

舍入模式舍入方向
ROUND_CEILING正无穷
ROUND_FLOOR负无穷
ROUND_DOWN0
ROUND_UP0的反方向
ROUND_HALF_DOWN最接近的数,同样接近则舍入方向为零。
ROUND_HALF_EVEN最接近的数,同样接近时趋向偶数。
ROUND_HALF_UP最接近的数,同样接近则舍入到零的反方向
ROUND_05UP末位趋0或5
常量MAX_PRECMAX_EMAXMIN_EMINMIN_ETINY
32位425000000MAX_PREC-MAX_PREC-849999999
64位1e18-1MAX_PREC-MAX_PREC-(MAX_PREC-2)

上下文对象

在decimal中,通过上下文对象来管理精度、舍入规则等,可通过getcontextsetcontext来读取和更改。

>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[Inexact, FloatOperation, Rounded], traps=[InvalidOperation, DivisionByZero, Overflow])

decimal内置了三种上下文

>>> BasicContext
Context(prec=9, rounding=ROUND_HALF_UP, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[Clamped, InvalidOperation, DivisionByZero, Overflow, Underflow])
>>> ExtendedContext
Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[])
>>> DefaultContext
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])

如果希望自定义,可以通过Context的构造函数

Context(prec=None, rounding=None, Emin=None, Emax=None, capitals=None, clamp=None, flags=None, traps=None)

其中

  • prec为[1, MAX_PREC]范围内的整数,用于设置精度。
  • rounding 设置舍入方式。
  • EminEmax 给定指数所允许的外部上限。 Emin在 [MIN_EMIN, 0]范围内,Emax 在[0, MAX_EMAX]范围内。
  • capitals默认为1,此时指数符号为大写的E,为0是用小写e。
  • traps用于设置当前上下文的警告信息。
  • clamp 默认为0,如果设为 1,则指数e的表示范围在将被限制在 Emin - prec + 1 <= e <= Emax - prec + 1。 如果 clamp 为 0 则将适用较弱的条件: Decimal 实例调整后的指数最大值为 Emax。

除了getcontentext之外,还可以通过localcontext来获取当前上下文,其方法为

>>> with d.localcontext() as ctx:
...   print(ctx.prec)
...
28

报错与警告(signal)

在decimal中有14种警告信息(标准库里写的是10个,但源码中有14个):

DecimalException为基类外,另外13个警告信息为

Clamped指数超限InvalidOperation无效操作
DivisionByZero除零错误DivisionImpossible除法发生了舍入
Overflow溢出DivisionUndefined未定义的除法
Subnormal舍入前指数低于Emin
Underflow向下溢出FloatOperation与float运算
Rounded发生了舍入ConversionSyntax字符串转化不完美
Inexact不精确舍入InvalidContext上下文有歧义

数学模块其他内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微小冷

请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值