python精确计算包decimal,告别截断误差
本文已整合到这里:Python内置数学模块全整理,易查易阅
文章目录
- Decimal对象
- 常量和成员变量
- 上下文对象
- 报错与警告(signal)
- 数学模块其他内容
在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')
| 成员变量 | imag | real |
|---|---|---|
| 虚部 | 实部 |
| 函数 | |
|---|---|
| 返回自身 | conjugate,canonical,normalize返回最简形式,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, sqrt,copy_abs,copy_negate返回负值 |
| 舍入函数 | to_integral_exact,to_integral_value, to_integral |
| 转字符串 | to_eng_string转字符串,as_tuple 返回每一位数字的元组 |
| 返回分数 | as_integer_ratio= a b \frac{a}{b} ba |
| 移位函数 | adjusted 返回科学计数法的指数 |
| 相邻数字 | next_minus,next_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_signal,compare_total,compare_total_mag | |
a.copy_sign(b)= ∣ b ∣ b a \frac{|b|}{b}a b∣b∣a | |
same_quantum如有相同指数则返回1 | |
| 相邻值 | next_toward返回趋向b的最接近于a的数字 |
| 最值 | max, min, max_mag, min_mag, 例如a.max(b)等价于max(a,b) |
常量和成员变量
| 舍入模式 | 舍入方向 |
|---|---|
| ROUND_CEILING | 正无穷 |
| ROUND_FLOOR | 负无穷 |
| ROUND_DOWN | 0 |
| ROUND_UP | 0的反方向 |
| ROUND_HALF_DOWN | 最接近的数,同样接近则舍入方向为零。 |
| ROUND_HALF_EVEN | 最接近的数,同样接近时趋向偶数。 |
| ROUND_HALF_UP | 最接近的数,同样接近则舍入到零的反方向 |
| ROUND_05UP | 末位趋0或5 |
| 常量 | MAX_PREC | MAX_EMAX | MIN_EMIN | MIN_ETINY |
|---|---|---|---|---|
| 32位 | 425000000 | MAX_PREC | -MAX_PREC | -849999999 |
| 64位 | 1e18-1 | MAX_PREC | -MAX_PREC | -(MAX_PREC-2) |
上下文对象
在decimal中,通过上下文对象来管理精度、舍入规则等,可通过getcontext和setcontext来读取和更改。
>>> 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设置舍入方式。Emin和Emax给定指数所允许的外部上限。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 | 上下文有歧义 |
数学模块其他内容
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
