Python之decimal模块的使用
decimal模块的作用
Decimal模块的实例可以准确地表示任何数,对其上或其下取整,还可以限制有效数字个数。
1、Decimal创建的使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import decimal fmt = '{0:<25} {1:<25}' print(fmt.format('Input', 'Output')) print(fmt.format('-' * 25, '-' * 25)) # 输入整数 print(fmt.format(5, decimal.Decimal(5))) # 输入字符串 print(fmt.format('3.14', decimal.Decimal('3.14'))) f = 0.1 print(fmt.format(repr(f), decimal.Decimal(str(f)))) print('{0:<23g} {1:<25}'.format( f, # 把浮点数转换成十进制数 str(decimal.Decimal.from_float(f))[:25]))
测试效果
Input Output ------------------------- ------------------------- 5 5 3.14 3.14 0.1 0.1 0.1 0.10000000000000000555111
2、用元组的形式创建小数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import decimal # 元组解析 # 元组参数一: 0,表示正数,1,表示负数 # 元组参数二:十进制整数,例如下面是198 # 元组参数三:小数点几位 t = (1, (1, 9, 8), -2) print('Input :', t) print('Decimal :', decimal.Decimal(t))
测试结果
Input : (1, (1, 9, 8, 8), -2)
Decimal : -19.88
3、小数的格式化
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import decimal d = decimal.Decimal(1.1) # %f ——保留小数点后面六位有效数字 %.3f,保留3位小数位 # %e ——保留小数点后面六位有效数字,指数形式输出 %.3e,保留3位小数位,使用科学计数法 # %g ——在保证六位有效数字的前提下,使用小数方式,否则使用科学计数法 %.3g,保留3位有效数字,使用小数或科学计数法 print('精确度:') print('{:.1}'.format(d)) print('{:.2}'.format(d)) print('{:.3}'.format(d)) print('{:.18}'.format(d)) print('\n宽度和精度相结合') print('{:5.1f} {:5.1g}'.format(d, d)) print('{:5.2f} {:5.2g}'.format(d, d)) print('\n0填充') # 格式05:表示共5位,用0填充,.1表示小数据在左边第一位 print('{:05.1}'.format(d)) print('{:05.2}'.format(d)) print('{:05.3}'.format(d))
测试结果
精确度: 1 1.1 1.10 1.10000000000000009 宽度和精度相结合 1.1 1 1.10 1.1 0填充 00001 001.1 01.10
4、Decimal算术运算
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import decimal a = decimal.Decimal('5.1') b = decimal.Decimal('3.14') c = 4 d = 3.14 # 打印变量附值 print('a =', repr(a)) print('b =', repr(b)) print('c =', repr(c)) print('d =', repr(d)) print() # Decimal()对象的加减乘除 print('a + b =', a + b) print('a - b =', a - b) print('a * b =', a * b) print('a / b =', a / b) print() # Decimal()对象与int进行的加减乘除 print('a + c =', a + c) print('a - c =', a - c) print('a * c =', a * c) print('a / c =', a / c) print() # Decimal()对象不支持与float进行的加减乘除 print('a + d =', end=' ') try: print(a + d) except TypeError as e: print(e)
测试结果
a = Decimal('5.1') b = Decimal('3.14') c = 4 d = 3.14 a + b = 8.24 a - b = 1.96 a * b = 16.014 a / b = 1.624203821656050955414012739 a + c = 9.1 a - c = 1.1 a * c = 20.4 a / c = 1.275 a + d = unsupported operand type(s) for +: 'decimal.Decimal' and 'float'
5、Decimal数学的特殊值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import decimal for value in ['Infinity', 'NaN', '0']: print(decimal.Decimal(value), decimal.Decimal('-' + value)) print() # 数学的正无穷大和负无穷大 print('Infinity + 1:', (decimal.Decimal('Infinity') + 1)) print('-Infinity + 1:', (decimal.Decimal('-Infinity') + 1)) # NaN与正无穷大和负无穷大比较 print(decimal.Decimal('NaN') == decimal.Decimal('Infinity')) print(decimal.Decimal('NaN') != decimal.Decimal(1))
测试结果
Infinity -Infinity NaN -NaN 0 -0 Infinity + 1: Infinity -Infinity + 1: -Infinity False True
6、decimal上下文属性的获取
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import decimal context = decimal.getcontext() print('Emax =', context.Emax) print('Emin =', context.Emin) print('capitals =', context.capitals) print('prec =', context.prec) print('rounding =', context.rounding) print('flags =') for f, v in context.flags.items(): print(' {}: {}'.format(f, v)) print('traps =') for t, v in context.traps.items(): print(' {}: {}'.format(t, v))
测试结果
Emax = 999999 Emin = -999999 capitals = 1 prec = 28 rounding = ROUND_HALF_EVEN flags = <class 'decimal.InvalidOperation'>: False <class 'decimal.FloatOperation'>: False <class 'decimal.DivisionByZero'>: False <class 'decimal.Overflow'>: False <class 'decimal.Underflow'>: False <class 'decimal.Subnormal'>: False <class 'decimal.Inexact'>: False <class 'decimal.Rounded'>: False <class 'decimal.Clamped'>: False traps = <class 'decimal.InvalidOperation'>: True <class 'decimal.FloatOperation'>: False <class 'decimal.DivisionByZero'>: True <class 'decimal.Overflow'>: True <class 'decimal.Underflow'>: False <class 'decimal.Subnormal'>: False <class 'decimal.Inexact'>: False <class 'decimal.Rounded'>: False <class 'decimal.Clamped'>: False
7、用Decimal的上文属性prec,来控制精度
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import decimal d = decimal.Decimal('0.123456') for i in range(1, 5): decimal.getcontext().prec = i print(i, ':', d, d * 1)
测试结果
1 : 0.123456 0.1 2 : 0.123456 0.12 3 : 0.123456 0.123 4 : 0.123456 0.1235
8、取整的示例
ROUND_CEILING : 总是趋向无穷大向上取整。
ROUND_DOWN : 总是趋向0取整。
ROUND_FLOOR : 总是趋向无穷大向下取整。
ROUND_HALF_DOWN : 如果最后一个有效数字大于或等于5则朝0反方向取整;否则,趋向0取整。
ROUND_HALF_EVEN : 类似于ROUND_HALF_DOWN,不过如果最后一个有效数字为5,则值检查前一位。偶数值会导致结果向下取整,奇数值导致结果向上取整。
ROUND_HALF_UP : 类似于ROUND_HALF_DOWN,不过如果最后一个有效数字为5,则值会朝0的反方向取整。
ROUND_UP : 朝0的反方向取整
ROUND_05UP :如果最后一位是0或5,则朝0的反方向取整;否则向0取整。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import decimal context = decimal.getcontext() ROUNDING_MODES = [ 'ROUND_CEILING', 'ROUND_DOWN', 'ROUND_FLOOR', 'ROUND_HALF_DOWN', 'ROUND_HALF_EVEN', 'ROUND_HALF_UP', 'ROUND_UP', 'ROUND_05UP', ] header_fmt = '{:10} ' + ' '.join(['{:^8}'] * 6) print(header_fmt.format( ' ', '1/8 (1)', '-1/8 (1)', '1/8 (2)', '-1/8 (2)', '1/8 (3)', '-1/8 (3)', )) for rounding_mode in ROUNDING_MODES: print('{0:10}'.format(rounding_mode.partition('_')[-1]), end=' ') for precision in [1, 2, 3]: context.prec = precision context.rounding = getattr(decimal, rounding_mode) value = decimal.Decimal(1) / decimal.Decimal(8) print('{0:^8}'.format(value), end=' ') value = decimal.Decimal(-1) / decimal.Decimal(8) print('{0:^8}'.format(value), end=' ') print()
测试效果
1/8 (1) -1/8 (1) 1/8 (2) -1/8 (2) 1/8 (3) -1/8 (3) CEILING 0.2 -0.1 0.13 -0.12 0.125 -0.125 DOWN 0.1 -0.1 0.12 -0.12 0.125 -0.125 FLOOR 0.1 -0.2 0.12 -0.13 0.125 -0.125 HALF_DOWN 0.1 -0.1 0.12 -0.12 0.125 -0.125 HALF_EVEN 0.1 -0.1 0.12 -0.12 0.125 -0.125 HALF_UP 0.1 -0.1 0.13 -0.13 0.125 -0.125 UP 0.2 -0.2 0.13 -0.13 0.125 -0.125 05UP 0.1 -0.1 0.12 -0.12 0.125 -0.125
9、本地上下文
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import decimal with decimal.localcontext() as c: c.prec = 2 print('Local precision:', c.prec) print('3.14 / 3 =', (decimal.Decimal('3.14') / 3)) print() print('Default precision:', decimal.getcontext().prec) print('3.14 / 3 =', (decimal.Decimal('3.14') / 3))
测试效果
Local precision: 2
3.14 / 3 = 1.0
Default precision: 28
3.14 / 3 = 1.046666666666666666666666667
10、多实例控制精度
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
测试效果
PI : 3.14
RESULT: 6.3114
11、decimal上下文全局线程的示例(即每个线程配置不一样的精度,实现不同线程区分精度)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import decimal import threading from queue import PriorityQueue class Multiplier(threading.Thread): def __init__(self, a, b, prec, q): self.a = a self.b = b self.prec = prec self.q = q threading.Thread.__init__(self) def run(self): c = decimal.getcontext().copy() c.prec = self.prec decimal.setcontext(c) self.q.put((self.prec, self.a * self.b)) a = decimal.Decimal('3.14') b = decimal.Decimal('1.234') q = PriorityQueue() threads = [Multiplier(a, b, i, q) for i in range(1, 6)] for t in threads: t.start() for t in threads: t.join() for i in range(5): prec, value = q.get() print('{} {}'.format(prec, value))
测试效果
1 4 2 3.9 3 3.87 4 3.875 5 3.8748
12、decimal模块log函数的使用示例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import decimal d = decimal.Decimal(100) print('d :', d) print('log10 :', d.log10()) print('ln :', d.ln())
测试效果
d : 100 log10 : 2 ln : 4.605170185988091368035982909