Python 數字運算及格式化

ckxllf發表於2020-01-15

  數字運算及格式化

  本篇幅主要針對浮點數的一些計算及格式化輸出。

  round()

  Python 提供的內建函式 round(number[, ndigits]) 可用於簡單的舍入運算。如下示例:

  >>> round(1.23)

  1

  >>> round(1.23, 1)

  1.2

  >>> round(1.27, 1)

  1.3

  >>> round(-1.27, 1)

  -1.3

  >>> round(1.2346, 3)

  1.235

  round() 函式返回四捨五入到小數點後 ndigits 位精度的數字。如果 ndigits 預設為 None,則返回最接近的整數。

  ndigits 引數可以是負數,在這種情況下,舍入運算會作用在十位、百位、千位等上面。例如:

  >>> x = 1234567

  >>> round(x, -1)

  1234570

  >>> round(x, -2)

  1234600

  >>> round(x, -3)

  1235000

  如果一個數字剛好在兩個邊界中間時,呼叫 round() 函式會返回離它最近的偶數。例如 round(0.5) 和 round(-0.5) 返回的結果都是 0。如下示例:

  >>> round(0.5)

  0

  >>> round(-0.5)

  0

  有時運用 round() 會得不到期望的值。例如 round(2.675, 2) 得到的是 2.67,卻不是期望得到的 2.68。如下:

  >>> round(2.675, 2)

  2.67

  這並非是 bug。Python 文件也給出了其中的註解,這是因為大多數十進位制小數實際上都不能以浮點數精確地表示。

  Note:The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.

  若需瞭解更多資訊可以訪問: Floating Point Arithmetic: Issues and Limitations。

  格式化輸出

  數字舍入跟格式化不能混淆。若是簡單輸出指定寬度的數,可以考慮用 format(),不需要使用 round()。在格式化的時候指定精度就可以。例如:

  >>> x = 1234.56789

  >>> # 精確到小數點後兩位

  ... format(x, '0.2f')

  '1234.57'

  >>> # 以 10 個字元右對齊,精確到小數點 1 位

  ... format(x, '>10.1f')

  ' 1234.6'

  >>> # 左對齊

  ... format(x, '<10.1f')

  '1234.6 '

  >>> # 居中

  ... format(x, '^10.1f')

  ' 1234.6 '

  >>> # 包含千分位分隔符

  ... format(x, ',')

  '1,234.56789'

  >>> format(x, '0,.1f')

  '1,234.6'

  >>>

  同樣可以使用指數記法,將 f 改成 e 或者 E(取決於指數輸出的大小寫形式)。示例如下:

  >>> format(x, 'e')

  '1.234568e+03'

  >>> format(x, '0.2E')

  '1.23E+03'

  指定寬度和精度的一般形式為 '[<>^]?width[,]?(.digits)?',其中 width 和 digits 為整數,? 代表可選部分。這種格式可以用在字串的 format() 方法中。示例如下:

  >>> 'The value is {:0,.2f}'.format(x)

  'The value is 1,234.57'

  精確運算 鄭州較好的婦科醫院

  因為浮點數運算存在誤差,不建議嘗試使用舍入浮點值來“修正”表面上看起來正確的問題。示例如下:

  >>> a = 2.1

  >>> b = 4.2

  >>> c = a + b

  >>> c

  6.300000000000001

  >>> c = round(c, 2) # 不建議這麼做

  >>> c

  6.3

  一般使用浮點數的情況下,不建議這麼做。這些誤差在一般情況下能夠被容忍的。但是如果涉及到比如金融領域(不允許小誤差存在)的情況下,建議考慮使用 decimal 模組。

  decimal

  由於浮點數不能精確的表示十進位制,會出現上述簡單數學運算出現誤差的情況。

  Python 提供的 decimal 模組,在損耗一定效能的前提下,能夠解決這個問題。如下示例:

  >>> from decimal import Decimal

  >>> a = Decimal('4.2')

  >>> b = Decimal('2.1')

  >>> a + b

  Decimal('6.3')

  >>> print(a + b)

  6.3

  >>> (a + b) == Decimal('6.3')

  True

  雖然程式碼寫起來會有些奇怪,但是 Decimal 物件能夠像普通的浮點數支援所有的常用數學運算。在使用 print 的情況下,跟普通數字沒有區別。

  decimal 允許控制計算,包括精確位數跟舍入運算。可以透過建立上下文管理器進行設定更改,示例如下:

  >>> from decimal import localcontext

  >>> a = Decimal('1.3')

  >>> b = Decimal('1.7')

  >>> print(a/b)

  0.7647058823529411764705882353

  >>> with localcontext() as ctx:

  ... ctx.prec = 3 # 精確位數

  ... print(a/b)

  ...

  0.765

  >>> with localcontext() as ctx:

  ... ctx.prec = 50 # 精確位數

  ... print(a/b)

  ...

  0.76470588235294117647058823529411764705882352941176

  decimal 運用場景,更常見的是在金融領域(不能容忍小誤差存在)。

  但是 decimal,需要損耗效能進行精確的運算,在普通領域,甚至於科學領域的大多數運算,使用普通浮點數型別是普遍的做法。

  除了真實世界很少要求要精確到普通浮點數能提供的 17 位精度的原因外,還有進行大量運算的時候,普通浮點數要快得多,這同樣是需要衡量的地方。

  但也不能完全忽略誤差,誤差出現,同樣需要研究並理解誤差產生的來源。

  參考資料

  來源

  David M. Beazley;Brian K. Jones.Python Cookbook, 3rd Edtioni.O’Reilly Media.2013.

  '2. Built-in Functions".docs.python.org.Retrieved 6 January 2020

  “15. Floating Point Arithmetic: Issues and Limitations”.docs.python.org.Retrieved 7 January 2020

  “9.4. decimal — Decimal fixed point and floating point arithmetic”.docs.python.org.Retrieved 11 January 2020


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69945560/viewspace-2673423/,如需轉載,請註明出處,否則將追究法律責任。

相關文章