本文已整合到这里: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')
成员变量 | 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 | 上下文有歧义 |