python裡的decimal型別轉換
https://blog.csdn.net/kebu12345678/article/details/54845908
[Python標準庫]decimal——定點數和浮點數的數學運算
作用:使用定點數和浮點數的小數運算。
Python 版本:2.4 及以後版本
decimal 模組實現了定點和浮點算術運算子,使用的是大多數人所熟悉的模型,而不是程式設計師熟悉的模型,即大多數計算機硬體實現的 IEEE 浮點數運算。Decimal 例項可以準確地表示任何數,對其上取整或下取整,還可以對有效數字個數加以限制。
Decimal
小數值表示為 Decimal 類的例項。建構函式取一個整數或字串作為引數。使用浮點數建立 Decimal 之前,可以先將浮點數轉換為一個字串,使呼叫者能夠顯式地處理值得位數,倘若使用硬體浮點數表示則無法準確地表述。另外,利用類方法 from_float() 可以轉換為精確的小數表示。
[python] view plain copy
- import decimal
- fmt = '{0:<25} {1:<25}'
- print fmt.format('Input', 'Output')
- print fmt.format('-' * 25, '-' * 25)
- # Integer
- print fmt.format(5, decimal.Decimal(5))
- # String
- print fmt.format('3.14', decimal.Decimal('3.14'))
- # Float
- f = 0.1
- print fmt.format(repr(f), decimal.Decimal(str(f)))
- print fmt.format('%.23g' % f, str(decimal.Decimal.from_float(f))[:25])
浮點數值 0.1 並不表示為一個精確的二進位制值,所以 float 的表示與 Decimal 值不同。在這個輸出中它被截斷為 25 個字元。
Decimal 還可以由元組建立,其中包含一個符號標誌(0 表示正,1 表示負)、數字 tuple 以及一個整數指數。
[python] view plain copy
- import decimal
- # Tuple
- t = (1, (1, 1), -2)
- print 'Input :', t
- print 'Decimal:', decimal.Decimal(t)
基於元組的表示建立時不太方便,不過它提供了一種可移植的方式,可以匯出小數值而不會損失精度。tuple 形式可以在網路上傳輸,或者在不支援精確小數值得資料庫中儲存,以後再轉回回 Decimal 例項。
算術運算
Decimal 過載了簡單的算術運算子,所以可以採用內建數值型別同樣的方式處理 Decimal 例項。
[python] view plain copy
- 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 'a + b =', a + b
- print 'a - b =', a - b
- print 'a * b =', a * b
- print 'a / b =', a / b
- print 'a + c =', a + c
- print 'a - c =', a - c
- print 'a * c =', a * c
- print 'a / c =', a / c
- print 'a + d =',
- try:
- print a + d
- except TypeError, e:
- print e
Decimal 運算子還接受整數引數,不過浮點數值必須轉換為 Decimal 例項。
除了基本算術運算,Decimal 還包括一些方法來查詢以 10 為底的對數和自然對數。log10() 和 ln() 返回的值都是 Decimal 例項,所以可以與其他值一樣直接在公式中使用。
特殊值
除了期望的數字值,Decimal 還可以表示很多特殊值,包括正負無窮大值、“不是一個數”(NaN)和 0。
[python] view plain copy
- import decimal
- for value in [ 'Infinity', 'NaN', '0' ]:
- print decimal.Decimal(value), decimal.Decimal('-' + value)
- # Math with infinity
- print 'Infinity + 1:', (decimal.Decimal('Infinity') + 1)
- print '-Infinity + 1:', (decimal.Decimal('-Infinity') + 1)
- # Print comparing NaN
- print decimal.Decimal('NaN') == decimal.Decimal('Infinity')
- print decimal.Decimal('NaN') != decimal.Decimal(1)
與無窮大值相加會返回另一個無窮大值。與 NaN 比較相等性總會返回 false,而比較不等性總會返回 true。與 NaN 比較大小來確定排序順序沒有明確定義,這會導致一個錯誤。
上下文
到目前為止,前面的例子使用的都是 decimal 模組的預設行為。還可以使用一個上下文(context)覆蓋某些設定,如保持精度、如何完成取整、錯誤處理等等。上下文可以應用於一個執行緒中的所有 Decimal 例項,或者區域性應用於一個小程式碼區。
1. 當前上下文
要獲取當前全域性上下文,可以使用 getcontext()。
[python] view plain copy
- import decimal
- import pprint
- 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 ='
- pprint.pprint(context.flags)
- print 'traps ='
- pprint.pprint(context.traps)
這個示例指令碼顯示了 Context 的公共屬性。
2. 精度
上下文的 prec 屬性控制著作為算術運算結果所建立的新值的精度。字面量值會按這個屬性保持精度。
[python] view plain copy
- import decimal
- d = decimal.Decimal('0.123456')
- for i in range(4):
- decimal.getcontext().prec = i
- print i, ':', d, d * 1
要改變精度,可以直接為這個屬性賦一個新值。
3. 取整
取整有多種選擇,以保證值在所需精度範圍內。
- 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 取整。
[python] view plain copy
- 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]),
- 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),
- value = decimal.Decimal(-1) / decimal.Decimal(8)
- print '{0:^8}'.format(value),
這個程式顯示了使用不同演算法將同一個值取整為不同精度的效果。
4. 區域性上下文
使用 Python 2.5 或以後版本時,可以使用 with 語句對一個程式碼塊應用上下文。
[python] view plain copy
- 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 'Default precision:', decimal.getcontext().prec
- print '3.14 / 3 =', (decimal.Decimal('3.14') / 3)
Context 支援 with 使用的上下文管理器 API,所以這個設定只在塊內應用。
5. 各例項上下文
上下文還可以用來構造 Decimal 例項,然後可以從這個上下文繼承精度和轉換的取整引數。
[python] view plain copy
- import decimal
- # Set up a context with limited precision
- c = decimal.getcontext().copy()
- c.prec = 3
- # Create our constant
- pi = c.create_decimal('3.1415')
- # The constant value is rounded off
- print 'PI :', pi
- # The result of using the constant uses the global context
- print 'RESULT:', decimal.Decimal('2.01') * pi
這樣一來,應用就可以區別於使用者資料精度而另外選擇常量值精度。
6. 執行緒
“全域性”上下文實際上是執行緒本地上下文,所以完全可以使用不同的值分別配置各個執行緒。
[python] view plain copy
- 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, a * b) )
- return
- a = decimal.Decimal('3.14')
- b = decimal.Decimal('1.234')
- # A PriorityQueue will return values sorted by precision, no matter
- # what order the threads finish.
- 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 prec, '\t', value
這個例子使用指定的值建立一個新的上下文,然後安裝到各個執行緒中。