decimal模塊的作用
Decimal模塊的實例可以准確地表示任何數,對其上或其下取整,還可以限制有效數字個數。
1、Decimal創建的使用

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、用元組的形式創建小數

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、小數的格式化

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算術運算

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數學的特殊值

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上下文屬性的獲取

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,來控制精度

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取整。

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、本地上下文

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、多實例控制精度

測試效果
PI : 3.14
RESULT: 6.3114
11、decimal上下文全局線程的示例(即每個線程配置不一樣的精度,實現不同線程區分精度)

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函數的使用示例

import decimal d = decimal.Decimal(100) print('d :', d) print('log10 :', d.log10()) print('ln :', d.ln())
測試效果
d : 100 log10 : 2 ln : 4.605170185988091368035982909