"decimal" --- 十進位固定點和浮點運算
************************************

**原始碼：**Lib/decimal.py

======================================================================

"decimal" 模組提供對快速且正確捨入的十進位浮點運算的支援。它提供了優於
"float" 資料型別的幾項優勢：

* Decimal 「是基於一個浮點模型，該模型在設計時考量了人類的需求，並且必
  然有一個最重要的指導原則——電腦必須提供一種與人們在學校學到的算術相同
  運作方式的算術。」——摘自十進位算術規格。

* Decimal 數字可以被精確表示。相對地，像 "1.1" 和 "2.2" 這樣的數字在二
  進位浮點數中沒有精確的表示方式。終端使用者通常不會期望 "1.1 + 2.2"
  顯示為 "3.3000000000000003"，但這正是二進位浮點數的表現。

* 精確性延續到算術運算中。在十進位浮點數中，"0.1 + 0.1 + 0.1 - 0.3" 完
  全等於零。在二進位浮點數中，結果是 "5.5511151231257827e-017"。雖然接
  近零，但這些差異會妨礙可靠的相等性測試，並且差異可能累積。因此，在具
  有嚴格相等不變量的會計應用程式中，decimal 是首選。

* decimal 模組包含了有效位數的概念，因此 "1.30 + 1.20" 等於 "2.50"。尾
  隨零被保留以表示有效性。這是金融應用程式的慣用呈現方式。對於乘法，「
  教科書」方法使用被乘數中的所有數字。例如，"1.3 * 1.2" 得到 "1.56"，
  而 "1.30 * 1.20" 得到 "1.5600"。

* 與基於硬體的二進位浮點數不同，decimal 模組具有使用者可變的精度（預設
  為 28 位），可以根據給定問題的需要設定得足夠大：

  >>> from decimal import *
  >>> getcontext().prec = 6
  >>> Decimal(1) / Decimal(7)
  Decimal('0.142857')
  >>> getcontext().prec = 28
  >>> Decimal(1) / Decimal(7)
  Decimal('0.1428571428571428571428571429')

* 二進位和十進位浮點數都是根據已發布的標準實作的。雖然內建的 float 型
  別只暴露其功能的一小部分，但 decimal 模組暴露了標準的所有必要部分。
  必要時，程式設計師對捨入和訊號處理有完全的控制權。這包括透過使用例外
  來阻止任何不精確運算以強制執行精確算術的選項。

* decimal 模組被設計為支援「不帶偏見地同時支援精確無捨入的十進位算術（
  有時稱為固定點算術）和有捨入的浮點算術。」——摘自十進位算術規格。

模組設計圍繞三個概念：decimal 數字、算術情境和訊號。

decimal 數字是不可變的。它有符號、係數數字和指數。為了保持有效性，係數
數字不會截斷尾隨零。Decimal 也包含特殊值，如 "Infinity"、"-Infinity"
和 "NaN"。標準也區分 "-0" 和 "+0"。

算術情境是一個指定精度、捨入規則、指數限制、指示運算結果的旗標，以及決
定訊號是否被視為例外的陷阱啟用器的環境。捨入選項包括 "ROUND_CEILING"、
"ROUND_DOWN"、"ROUND_FLOOR"、"ROUND_HALF_DOWN"、"ROUND_HALF_EVEN"、
"ROUND_HALF_UP"、"ROUND_UP" 和 "ROUND_05UP"。

訊號是在計算過程中產生的例外條件群組。根據應用程式的需求，訊號可能被忽
略、視為資訊性質，或被視為例外。decimal 模組中的訊號包括："Clamped"、
"InvalidOperation"、"DivisionByZero"、"Inexact"、"Rounded"、
"Subnormal"、"Overflow"、"Underflow" 和 "FloatOperation"。

每個訊號都有一個旗標和一個陷阱啟用器。當遇到訊號時，其旗標被設定為一，
然後，如果陷阱啟用器被設定為一，就會引發例外。旗標是黏性的，因此使用者
需要在監控計算之前重設它們。

也參考:

  * IBM 的一般十進位算術規範，一般十進位算術規範。


快速入門教學
============

使用 decimal 的通常起始步驟是引入模組、使用 "getcontext()" 檢視目前的
情境，以及若有必要的話，設定精度、捨入方式或啟用陷阱的新值：

   >>> from decimal import *
   >>> getcontext()
   Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
           capitals=1, clamp=0, flags=[], traps=[Overflow, DivisionByZero,
           InvalidOperation])

   >>> getcontext().prec = 7       # 設定新的精度

Decimal 實例可以從整數、字串、浮點數或 tuple 建構。從整數或浮點數建構
會對該整數或浮點數的值進行精確轉換。Decimal 數字包括特殊值，例如代表「
非數字」的 "NaN"、正負 "Infinity" 和 "-0"：：

   >>> getcontext().prec = 28
   >>> Decimal(10)
   Decimal('10')
   >>> Decimal('3.14')
   Decimal('3.14')
   >>> Decimal(3.14)
   Decimal('3.140000000000000124344978758017532527446746826171875')
   >>> Decimal((0, (3, 1, 4), -2))
   Decimal('3.14')
   >>> Decimal(str(2.0 ** 0.5))
   Decimal('1.4142135623730951')
   >>> Decimal(2) ** Decimal('0.5')
   Decimal('1.414213562373095048801688724')
   >>> Decimal('NaN')
   Decimal('NaN')
   >>> Decimal('-Infinity')
   Decimal('-Infinity')

如果 "FloatOperation" 訊號被捕捉，在建構函式或排序比較中意外混用
decimal 和 float 會引發例外：

   >>> c = getcontext()
   >>> c.traps[FloatOperation] = True
   >>> Decimal(3.14)
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   decimal.FloatOperation: [<class 'decimal.FloatOperation'>]
   >>> Decimal('3.5') < 3.7
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   decimal.FloatOperation: [<class 'decimal.FloatOperation'>]
   >>> Decimal('3.5') == 3.5
   True

在 3.3 版被加入.

新 Decimal 的精度僅由輸入的數字位數決定。情境精度和捨入只會在算術運算
期間發揮作用。

   >>> getcontext().prec = 6
   >>> Decimal('3.0')
   Decimal('3.0')
   >>> Decimal('3.1415926535')
   Decimal('3.1415926535')
   >>> Decimal('3.1415926535') + Decimal('2.7182818285')
   Decimal('5.85987')
   >>> getcontext().rounding = ROUND_UP
   >>> Decimal('3.1415926535') + Decimal('2.7182818285')
   Decimal('5.85988')

如果超過 C 版本的內部限制，建構 decimal 會引發 "InvalidOperation"：

   >>> Decimal("1e9999999999999999999")
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

在 3.3 版的變更.

Decimal 與 Python 的其他部分互動良好。以下是一個小小的 decimal 浮點數
展示：

   >>> data = list(map(Decimal, '1.34 1.87 3.45 2.35 1.00 0.03 9.25'.split()))
   >>> max(data)
   Decimal('9.25')
   >>> min(data)
   Decimal('0.03')
   >>> sorted(data)
   [Decimal('0.03'), Decimal('1.00'), Decimal('1.34'), Decimal('1.87'),
    Decimal('2.35'), Decimal('3.45'), Decimal('9.25')]
   >>> sum(data)
   Decimal('19.29')
   >>> a,b,c = data[:3]
   >>> str(a)
   '1.34'
   >>> float(a)
   1.34
   >>> round(a, 1)
   Decimal('1.3')
   >>> int(a)
   1
   >>> a * 5
   Decimal('6.70')
   >>> a * b
   Decimal('2.5058')
   >>> c % a
   Decimal('0.77')

Decimal 可以（透過 "format()" 內建函式或 f-string（f 字串））使用與內
建 "float" 型別相同的格式化語法（見 格式規格 (Format Specification) 迷
你語言）以固定點或科學記號格式化：

   >>> format(Decimal('2.675'), "f")
   '2.675'
   >>> format(Decimal('2.675'), ".2f")
   '2.68'
   >>> f"{Decimal('2.675'):.2f}"
   '2.68'
   >>> format(Decimal('2.675'), ".2e")
   '2.68e+0'
   >>> with localcontext() as ctx:
   ...     ctx.rounding = ROUND_DOWN
   ...     print(format(Decimal('2.675'), ".2f"))
   ...
   2.67

而且 Decimal 也提供一些數學函式：

>>> getcontext().prec = 28
>>> Decimal(2).sqrt()
Decimal('1.414213562373095048801688724')
>>> Decimal(1).exp()
Decimal('2.718281828459045235360287471')
>>> Decimal('10').ln()
Decimal('2.302585092994045684017991455')
>>> Decimal('10').log10()
Decimal('1')

"quantize()" 方法將數字捨入到固定的指數。此方法對於經常將結果捨入到固
定位數的金融應用程式很有用：

>>> Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32')
>>> Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)
Decimal('8')

如上所示，"getcontext()" 函式存取目前的情境並允許變更設定。這種方法滿
足大多數應用程式的需求。

對於更進階的工作，使用 "Context()" 建構函式來建立替代的 context 可能會
很有用。要啟用替代的 context，使用 "setcontext()" 函式。

根據標準，"decimal" 模組提供了兩個可直接使用的標準 context，
"BasicContext" 和 "ExtendedContext"。前者對除錯特別有用，因為許多陷阱
都被啟用了：

   >>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN)
   >>> setcontext(myothercontext)
   >>> Decimal(1) / Decimal(7)
   Decimal('0.142857142857142857142857142857142857142857142857142857142857')

   >>> ExtendedContext
   Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
           capitals=1, clamp=0, flags=[], traps=[])
   >>> setcontext(ExtendedContext)
   >>> Decimal(1) / Decimal(7)
   Decimal('0.142857143')
   >>> Decimal(42) / Decimal(0)
   Decimal('Infinity')

   >>> setcontext(BasicContext)
   >>> Decimal(42) / Decimal(0)
   Traceback (most recent call last):
     File "<pyshell#143>", line 1, in -toplevel-
       Decimal(42) / Decimal(0)
   DivisionByZero: x / 0

情境也有訊號旗標用於監控計算過程中遇到的例外條件。旗標會保持設定狀態直
到明確清除，因此最好在每組受監控的計算之前使用 "clear_flags()" 方法清
除旗標：

   >>> setcontext(ExtendedContext)
   >>> getcontext().clear_flags()
   >>> Decimal(355) / Decimal(113)
   Decimal('3.14159292')
   >>> getcontext()
   Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
           capitals=1, clamp=0, flags=[Inexact, Rounded], traps=[])

*flags* 條目顯示對 pi 的有理逼近已被捨入（超出情境精度的數字被丟棄），
並且結果是不精確的（一些被丟棄的數字非零）。

個別陷阱使用情境的 "traps" 屬性中的字典設定：

   >>> setcontext(ExtendedContext)
   >>> Decimal(1) / Decimal(0)
   Decimal('Infinity')
   >>> getcontext().traps[DivisionByZero] = 1
   >>> Decimal(1) / Decimal(0)
   Traceback (most recent call last):
     File "<pyshell#112>", line 1, in -toplevel-
       Decimal(1) / Decimal(0)
   DivisionByZero: x / 0

大多數程式只在程式開始時調整一次目前情境。在許多應用程式中，資料在迴圈
內透過單次轉換轉換為 "Decimal"。設定情境並建立 decimal 後，程式的大部
分操作資料的方式與其他 Python 數值型別沒有什麼不同。


Decimal 物件
============

class decimal.Decimal(value='0', context=None)

   基於 *value* 建構一個新的 "Decimal" 物件。

   *value* 可以是整數、字串、元組、"float" 或其他 "Decimal" 物件。如果
   沒有提供 *value*，則回傳 "Decimal('0')"。如果 *value* 是字串，在移
   除前後空白字元以及整個字串中的底線後，它應該符合十進位數字字串語法
   ：

      sign           ::=  '+' | '-'
      digit          ::=  '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
      indicator      ::=  'e' | 'E'
      digits         ::=  digit [digit]...
      decimal-part   ::=  digits '.' [digits] | ['.'] digits
      exponent-part  ::=  indicator [sign] digits
      infinity       ::=  'Infinity' | 'Inf'
      nan            ::=  'NaN' [digits] | 'sNaN' [digits]
      numeric-value  ::=  decimal-part [exponent-part] | infinity
      numeric-string ::=  [sign] numeric-value | [sign] nan

   在上面出現 "digit" 的地方也允許其他 Unicode 十進位數字。這些包括來
   自各種其他字母表的十進位數字（例如阿拉伯-印度數字和天城數字）以及全
   形數字 "'\uff10'" 到 "'\uff19'"。大小寫不重要，所以例如 "inf"、
   "Inf"、"INFINITY" 和 "iNfINity" 都是正無窮大的可接受拼寫。

   如果 *value* 是 "tuple"，它應該有三個元件：一個符號（"0" 代表正數或
   "1" 代表負數）、一個數字的 "tuple"，以及一個整數指數。例如，
   "Decimal((0, (1, 4, 1, 4), -3))" 回傳 "Decimal('1.414')"。

   如果 *value* 是 "float"，二進位浮點數值會被無損轉換為其精確的十進位
   等價值。這種轉換通常需要 53 位或更多位數的精度。例如，
   "Decimal(float('1.1'))" 轉換為
   "Decimal('1.100000000000000088817841970012523233890533447265625')"
   。

   *context* 精度不會影響儲存多少位數。這完全由 *value* 中的位數決定。
   例如，即使情境精度只有三位，"Decimal('3.00000')" 也會記錄所有五個零
   。

   *context* 引數的目的是決定當 *value* 是格式不正確的字串時該怎麼辦。
   如果情境捕捉 "InvalidOperation"，就會引發例外；否則，建構函式會回傳
   一個值為 "NaN" 的新 Decimal。

   一旦建構，"Decimal" 物件就是不可變的。

   在 3.2 版的變更: 建構函式的引數現在允許是 "float" 實例。

   在 3.3 版的變更: 如果設定了 "FloatOperation" 陷阱，"float" 引數會引
   發例外。預設情況下陷阱是關閉的。

   在 3.6 版的變更: 允許使用底線進行分組，就像程式碼中的整數和浮點數字
   面值一樣。

   Decimal 浮點數物件與其他內建數值型別（如 "float" 和 "int"）共享許多
   屬性。所有常用的數學運算和特殊方法都適用。同樣地，decimal 物件可以
   被複製、pickle 序列化、列印、用作字典鍵、用作集合元素、比較、排序，
   以及強制轉換為其他型別（如 "float" 或 "int"）。

   Decimal 物件的算術運算與整數和浮點數的算術運算之間有一些小差異。當
   餘數運算子 "%" 應用於 Decimal 物件時，結果的符號是 *被除數* 的符號
   ，而不是除數的符號：

      >>> (-7) % 4
      1
      >>> Decimal(-7) % Decimal(4)
      Decimal('-3')

   整數除法運算子 "//" 的行為類似，回傳真商的整數部分（向零截斷）而不
   是其底數，以保持通常的恆等式 "x == (x // y) * y + x % y"：

      >>> -7 // 4
      -2
      >>> Decimal(-7) // Decimal(4)
      Decimal('-1')

   "%" 和 "//" 運算子分別實作規格中描述的 "remainder" 和 "divide-
   integer" 運算。

   Decimal 物件通常不能在算術運算中與浮點數或 "fractions.Fraction" 實
   例結合：例如，嘗試將 "Decimal" 與 "float" 相加會引發 "TypeError"。
   但是，可以使用 Python 的比較運算子來比較 "Decimal" 實例 "x" 與另一
   個數字 "y"。這避免了在不同型別的數字之間進行相等比較時產生令人困惑
   的結果。

   在 3.2 版的變更: "Decimal" 實例與其他數值型別之間的混合型別比較現在
   完全支援。

   除了標準數值屬性外，decimal 浮點數物件也有許多專門的方法：

   adjusted()

      在移出係數的最右邊數字直到只剩下前導數字後，回傳調整後的指數：
      "Decimal('321e+5').adjusted()" 回傳七。用於確定最高有效數字相對
      於小數點的位置。

   as_integer_ratio()

      回傳一對表示給定 "Decimal" 實例作為分數的整數 "(n, d)"，以最簡形
      式且分母為正：

         >>> Decimal('-3.14').as_integer_ratio()
         (-157, 50)

      轉換是精確的。對無窮大引發 OverflowError，對 NaN 引發 ValueError
      。

   在 3.6 版被加入.

   as_tuple()

      回傳數字的 *named tuple* 表示形式："DecimalTuple(sign, digits,
      exponent)"。

   canonical()

      回傳引數的標準編碼。目前，"Decimal" 實例的編碼總是標準的，因此此
      運算回傳其引數不變。

   compare(other, context=None)

      比較兩個 Decimal 實例的值。"compare()" 回傳一個 Decimal 實例，如
      果任一運算元是 NaN，則結果是 NaN：

         a or b is a NaN  ==> Decimal('NaN')
         a < b            ==> Decimal('-1')
         a == b           ==> Decimal('0')
         a > b            ==> Decimal('1')

   compare_signal(other, context=None)

      此運算與 "compare()" 方法相同，除了所有 NaN 都會發出訊號。也就是
      說，如果兩個運算元都不是發出訊號的 NaN，那麼任何安靜的 NaN 運算
      元都會被視為發出訊號的 NaN。

   compare_total(other, context=None)

      使用抽象表示而不是數值來比較兩個運算元。類似於 "compare()" 方法
      ，但結果對 "Decimal" 實例給出全序。在此排序中，具有相同數值但不
      同表示的兩個 "Decimal" 實例比較為不相等：

      >>> Decimal('12.0').compare_total(Decimal('12'))
      Decimal('-1')

      安靜和發出訊號的 NaN 也包含在全序中。如果兩個運算元具有相同的表
      示，此函式的結果是 "Decimal('0')"；如果第一個運算元在全序中低於
      第二個，則為 "Decimal('-1')"；如果第一個運算元在全序中高於第二個
      運算元，則為 "Decimal('1')"。有關全序的詳細資訊，請參閱規範。

      此運算不受情境影響且是安靜的：不會變更旗標也不會執行捨入。例外情
      況下，如果第二個運算元無法精確轉換，C 版本可能會引發
      InvalidOperation。

   compare_total_mag(other, context=None)

      如 "compare_total()" 般使用抽象表示而不是值來比較兩個運算元，但
      忽略每個運算元的符號。"x.compare_total_mag(y)" 等於
      "x.copy_abs().compare_total(y.copy_abs())"。

      此運算不受情境影響且是安靜的：不會變更旗標也不會執行捨入。例外情
      況下，如果第二個運算元無法精確轉換，C 版本可能會引發
      InvalidOperation。

   conjugate()

      只是回傳 self，此方法僅為符合 Decimal 規範。

   copy_abs()

      回傳引數的絕對值。此運算不受情境影響且是安靜的：不會變更旗標也不
      會執行捨入。

   copy_negate()

      回傳引數的否定。此運算不受情境影響且是安靜的：不會變更旗標也不會
      執行捨入。

   copy_sign(other, context=None)

      回傳第一個運算元的副本，其符號被設定為與第二個運算元的符號相同。
      例如：

      >>> Decimal('2.3').copy_sign(Decimal('-1.5'))
      Decimal('-2.3')

      此運算不受情境影響且是安靜的：不會變更旗標也不會執行捨入。例外情
      況下，如果第二個運算元無法精確轉換，C 版本可能會引發
      InvalidOperation。

   exp(context=None)

      回傳給定數字的（自然）指數函式 "e**x" 的值。使用
      "ROUND_HALF_EVEN" 捨入模式正確地捨入結果。

      >>> Decimal(1).exp()
      Decimal('2.718281828459045235360287471')
      >>> Decimal(321).exp()
      Decimal('2.561702493119680037517373933E+139')

   classmethod from_float(f, /)

      僅接受 "float" 或 "int" 實例的替代建構函式。

      注意 "Decimal.from_float(0.1)" 與 "Decimal('0.1')" 不同。由於
      0.1 在二進位浮點數中無法精確表示，該值被儲存為最接近的可表示值
      "0x1.999999999999ap-4"。該值在十進位中的等價值是
      "0.1000000000000000055511151231257827021181583404541015625"。

      備註:

        從 Python 3.2 開始，"Decimal" 實例也可以直接從 "float" 建構。

         >>> Decimal.from_float(0.1)
         Decimal('0.1000000000000000055511151231257827021181583404541015625')
         >>> Decimal.from_float(float('nan'))
         Decimal('NaN')
         >>> Decimal.from_float(float('inf'))
         Decimal('Infinity')
         >>> Decimal.from_float(float('-inf'))
         Decimal('-Infinity')

      在 3.1 版被加入.

   classmethod from_number(number, /)

      替代建構函式，僅接受 "float"、"int" 或 "Decimal" 的實例，但不接
      受字串或 tuple。

         >>> Decimal.from_number(314)
         Decimal('314')
         >>> Decimal.from_number(0.1)
         Decimal('0.1000000000000000055511151231257827021181583404541015625')
         >>> Decimal.from_number(Decimal('3.14'))
         Decimal('3.14')

      在 3.14 版被加入.

   fma(other, third, context=None)

      融合乘加。回傳 self*other+third，對中間產品 self*other 不進行捨
      入。

      >>> Decimal(2).fma(3, 5)
      Decimal('11')

   is_canonical()

      如果引數是標準形式則回傳 "True"，否則回傳 "False"。目前，
      "Decimal" 實例總是標準形式，因此此運算總是回傳 "True"。

   is_finite()

      如果引數是有限數則回傳 "True"，如果引數是無窮大或 NaN 則回傳
      "False"。

   is_infinite()

      如果引數是正無窮大或負無窮大則回傳 "True"，否則回傳 "False"。

   is_nan()

      如果引數是（安靜或發出訊號的）NaN 則回傳 "True"，否則回傳
      "False"。

   is_normal(context=None)

      如果引數是 *正常* 有限數則回傳 "True"。如果引數是零、次正規、無
      窮大或 NaN 則回傳 "False"。

   is_qnan()

      如果引數是安靜 NaN 則回傳 "True"，否則回傳 "False"。

   is_signed()

      如果引數具有負號則回傳 "True"，否則回傳 "False"。注意零和 NaN 都
      可以帶有符號。

   is_snan()

      如果引數是發出訊號的 NaN 則回傳 "True"，否則回傳 "False"。

   is_subnormal(context=None)

      如果引數是次正規則回傳 "True"，否則回傳 "False"。

   is_zero()

      如果引數是（正或負）零則回傳 "True"，否則回傳 "False"。

   ln(context=None)

      回傳運算元的自然（以 e 為底）對數。使用 "ROUND_HALF_EVEN" 捨入模
      式正確地捨入結果。

   log10(context=None)

      回傳運算元的十進位對數。使用 "ROUND_HALF_EVEN" 捨入模式正確地捨
      入結果。

   logb(context=None)

      對於非零數字，回傳其運算元的調整指數作為 "Decimal" 實例。如果運
      算元是零，則回傳 "Decimal('-Infinity')" 並引發 "DivisionByZero"
      旗標。如果運算元是無窮大，則回傳 "Decimal('Infinity')"。

   logical_and(other, context=None)

      "logical_and()" 是一個邏輯運算，接受兩個 *logical operands* （參
      見 邏輯運算元）。結果是兩個運算元的逐位 "and"。

   logical_invert(context=None)

      "logical_invert()" 是一個邏輯運算。結果是運算元的逐位反轉。

   logical_or(other, context=None)

      "logical_or()" 是一個邏輯運算，接受兩個 *logical operands* （參
      見 邏輯運算元）。結果是兩個運算元的逐位 "or"。

   logical_xor(other, context=None)

      "logical_xor()" 是一個邏輯運算，接受兩個 *logical operands* （參
      見 邏輯運算元）。結果是兩個運算元的逐位互斥或。

   max(other, context=None)

      類似於 "max(self, other)"，但在回傳前會套用情境捨入規則，且
      "NaN" 值會被發出訊號或忽略（取決於情境以及它們是發出訊號或安靜的
      ）。

   max_mag(other, context=None)

      類似於 "max()" 方法，但比較是使用運算元的絕對值進行的。

   min(other, context=None)

      類似於 "min(self, other)"，但在回傳前會套用情境捨入規則，且
      "NaN" 值會被發出訊號或忽略（取決於情境以及它們是發出訊號或安靜的
      ）。

   min_mag(other, context=None)

      類似於 "min()" 方法，但比較是使用運算元的絕對值進行的。

   next_minus(context=None)

      回傳在給定情境中（或如果沒有提供情境則在目前執行緒的情境中）可表
      示的最大數字，且該數字小於給定的運算元。

   next_plus(context=None)

      回傳在給定情境中（或如果沒有提供情境則在目前執行緒的情境中）可表
      示的最小數字，且該數字大於給定的運算元。

   next_toward(other, context=None)

      如果兩個運算元不相等，回傳在第二個運算元方向上最接近第一個運算元
      的數字。如果兩個運算元在數值上相等，回傳第一個運算元的副本，其符
      號設定為與第二個運算元的符號相同。

   normalize(context=None)

      用於在目前情境或指定情境中產生等價類別的標準值。

      這與一元加法運算的語意相同，但如果最終結果是有限的，則會被簡化為
      最簡形式，移除所有尾隨零並保留符號。也就是說，當係數非零且是十的
      倍數時，係數除以十，指數增加 1。否則（係數為零）指數設定為 0。在
      所有情況下符號都不變。

      例如，"Decimal('32.100')" 和 "Decimal('0.321000e+2')" 都正規化為
      等價值 "Decimal('32.1')"。

      注意捨入是在簡化為最簡形式 *之前* 套用的。

      在規格的最新版本中，此運算也被稱為 "reduce"。

   number_class(context=None)

      回傳描述運算元 *類別* 的字串。回傳值是下列十個字串之一。

      * ""-Infinity""，表示運算元是負無窮大。

      * ""-Normal""，表示運算元是負的正規數。

      * ""-Subnormal""，表示運算元是負的次正規數。

      * ""-Zero""，表示運算元是負零。

      * ""+Zero""，表示運算元是正零。

      * ""+Subnormal""，表示運算元是正的次正規數。

      * ""+Normal""，表示運算元是正的正規數。

      * ""+Infinity""，表示運算元是正無窮大。

      * ""NaN""，表示運算元是安靜型 NaN（Not a Number，非數字）。

      * ""sNaN""，表示運算元是發訊型 NaN (signaling NaN)。

   quantize(exp, rounding=None, context=None)

      回傳一個值，該值等於第一個運算元在捨入後並具有第二個運算元的指數
      。

      >>> Decimal('1.41421356').quantize(Decimal('1.000'))
      Decimal('1.414')

      與其他運算不同，如果 quantize 運算後係數的長度大於精度，則會發出
      "InvalidOperation" 訊號。這保證了除非有錯誤條件，否則量化指數總
      是等於右運算元的指數。

      同樣與其他運算不同，quantize 永遠不會發出 Underflow 訊號，即使結
      果是次正規且不精確的。

      如果第二個運算元的指數大於第一個，則可能需要捨入。在這種情況下，
      捨入模式由 "rounding" 引數決定（如果有提供），否則由給定的
      "context" 引數決定；如果兩個引數都沒有提供，則使用目前執行緒情境
      的捨入模式。

      當結果指數大於 "Emax" 或小於 "Etiny()" 時會回傳錯誤。

   radix()

      回傳 "Decimal(10)"，這是 "Decimal" 類別執行所有算術運算的基數（
      底數）。包含此項是為了與規格相容。

   remainder_near(other, context=None)

      回傳 *self* 除以 *other* 的餘數。這與 "self % other" 不同之處在
      於餘數的符號被選擇以最小化其絕對值。更精確地說，回傳值是 "self -
      n * other"，其中 "n" 是最接近 "self / other" 精確值的整數，如果
      兩個整數同樣接近，則選擇偶數。

      如果結果是零，則其符號將是 *self* 的符號。

      >>> Decimal(18).remainder_near(Decimal(10))
      Decimal('-2')
      >>> Decimal(25).remainder_near(Decimal(10))
      Decimal('5')
      >>> Decimal(35).remainder_near(Decimal(10))
      Decimal('-5')

   rotate(other, context=None)

      回傳將第一個運算元的數字旋轉第二個運算元指定數量的結果。第二個運
      算元必須是在 -precision 到 precision 範圍內的整數。第二個運算元
      的絕對值給出要旋轉的位數。如果第二個運算元是正數，則向左旋轉；否
      則向右旋轉。第一個運算元的係數如有必要會在左側填補零以達到精度長
      度。第一個運算元的符號和指數不變。

   same_quantum(other, context=None)

      測試 self 和 other 是否具有相同的指數，或兩者是否都是 "NaN"。

      此運算不受情境影響且是安靜的：不會變更旗標也不會執行捨入。例外情
      況下，如果第二個運算元無法精確轉換，C 版本可能會引發
      InvalidOperation。

   scaleb(other, context=None)

      回傳第一個運算元，其指數由第二個運算元調整。等價地，回傳第一個運
      算元乘以 "10**other"。第二個運算元必須是整數。

   shift(other, context=None)

      回傳將第一個運算元的數字移位第二個運算元指定數量的結果。第二個運
      算元必須是在 -precision 到 precision 範圍內的整數。第二個運算元
      的絕對值給出要移位的位數。如果第二個運算元是正數，則向左移位；否
      則向右移位。移入係數的數字是零。第一個運算元的符號和指數不變。

   sqrt(context=None)

      回傳引數的完整精度平方根。

   to_eng_string(context=None)

      轉換為字串，如果需要指數則使用工程記號。

      工程記號的指數是 3 的倍數。這可能在小數點左側留下最多 3 位數字，
      並可能需要添加一個或兩個尾隨零。

      例如，這將 "Decimal('123E+1')" 轉換為 "Decimal('1.23E+3')"。

   to_integral(rounding=None, context=None)

      與 "to_integral_value()" 方法相同。保留 "to_integral" 名稱是為了
      與舊版本相容。

   to_integral_exact(rounding=None, context=None)

      捨入到最近的整數，如果發生捨入則適當地發出 "Inexact" 或
      "Rounded" 訊號。捨入模式由 "rounding" 參數決定（如果有提供），否
      則由給定的 "context" 決定。如果兩個參數都沒有提供，則使用目前情
      境的捨入模式。

   to_integral_value(rounding=None, context=None)

      捨入到最近的整數，不發出 "Inexact" 或 "Rounded" 訊號。如果有提供
      ，套用 *rounding*；否則，使用提供的 *context* 或目前情境中的捨入
      方法。

   Decimal 數字可以使用 "round()" 函式進行捨入：

   round(number)

   round(number, ndigits)

      如果沒有提供 *ndigits* 或為 "None"，回傳最接近 *number* 的 "int"
      ，平局時捨入到偶數，並忽略 "Decimal" 情境的捨入模式。如果
      *number* 是無窮大則引發 "OverflowError"，如果是（安靜或發出訊號
      的）NaN 則引發 "ValueError"。

      如果 *ndigits* 是 "int"，會遵守情境的捨入模式，並回傳代表
      *number* 捨入到 "Decimal('1E-ndigits')" 最近倍數的 "Decimal"；在
      這種情況下，"round(number, ndigits)" 等價於
      "self.quantize(Decimal('1E-ndigits'))"。如果 *number* 是安靜 NaN
      則回傳 "Decimal('NaN')"。如果 *number* 是無窮大、發出訊號的 NaN
      ，或 quantize 運算後係數的長度大於目前情境的精度，則引發
      "InvalidOperation"。換句話說，對於非邊界情況：

      * 如果 *ndigits* 是正數，回傳 *number* 捨入到 *ndigits* 小數位數
        ；

      * 如果 *ndigits* 是零，回傳 *number* 捨入到最近的整數；

      * 如果 *ndigits* 是負數，回傳 *number* 捨入到 "10**abs(ndigits)"
        的最近倍數。

      舉例來說：

         >>> from decimal import Decimal, getcontext, ROUND_DOWN
         >>> getcontext().rounding = ROUND_DOWN
         >>> round(Decimal('3.75'))     # 忽略情境捨入
         4
         >>> round(Decimal('3.5'))      # 平局捨入到偶數
         4
         >>> round(Decimal('3.75'), 0)  # 使用情境捨入
         Decimal('3')
         >>> round(Decimal('3.75'), 1)
         Decimal('3.7')
         >>> round(Decimal('3.75'), -1)
         Decimal('0E+1')


邏輯運算元
----------

"logical_and()"、"logical_invert()"、"logical_or()" 和 "logical_xor()"
方法期望它們的引數是 *logical operands*。*logical operand* 是指數和符
號都為零，且數字全部為 "0" 或 "1" 的 "Decimal" 實例。


Context 物件
============

Context 是算術運算的環境。它們控制精度、設定捨入規則、決定哪些訊號被視
為例外，並限制指數的範圍。

每個執行緒都有自己的目前情境，可以使用 "getcontext()" 和
"setcontext()" 函式來存取或變更：

decimal.getcontext()

   回傳作用中執行緒的目前情境。

decimal.setcontext(c, /)

   將作用中執行緒的目前情境設定為 *c*。

你也可以使用 "with" 陳述式和 "localcontext()" 函式來暫時變更作用中的情
境。

decimal.localcontext(ctx=None, **kwargs)

   回傳一個情境管理器，在進入 with 陳述式時會將作用中執行緒的目前情境
   設定為 *ctx* 的副本，並在退出 with 陳述式時恢復先前的情境。如果沒有
   指定情境，則使用目前情境的副本。*kwargs* 引數用於設定新情境的屬性。

   例如，以下程式碼將目前的 decimal 精度設定為 42 位，執行計算，然後自
   動恢復先前的情境：

      from decimal import localcontext

      with localcontext() as ctx:
          ctx.prec = 42   # 執行高精度計算
          s = calculate_something()
      s = +s  # 將最終結果捨入回預設精度

   使用關鍵字引數，程式碼如下：

      from decimal import localcontext

      with localcontext(prec=42) as ctx:
          s = calculate_something()
      s = +s

   如果 *kwargs* 提供了 "Context" 不支援的屬性，則引發 "TypeError"。如
   果 *kwargs* 為屬性提供了無效值，則引發 "TypeError" 或 "ValueError"
   。

   在 3.11 版的變更: "localcontext()" 現在支援透過關鍵字引數來設定
   context 屬性。

decimal.IEEEContext(bits)

   回傳一個 context 物件，其值被初始化為某個 IEEE 交換格式的適當值。引
   數必須是 32 的倍數且小於 "IEEE_CONTEXT_MAX_BITS"。

   在 3.14 版被加入.

新的 context 也可以使用下面描述的 "Context" 建構函式來建立。此外，該模
組提供了三個預製的 context：

decimal.BasicContext

   這是由通用十進位算術規格定義的標準 context。精度設定為九。捨入設定
   為 "ROUND_HALF_UP"。所有旗標都被清除。所有的 trap 都被啟用（視為例
   外），除了 "Inexact"、"Rounded" 和 "Subnormal"。

   因為很多 trap 都被啟用，這個 context 對於除錯很有用。

decimal.ExtendedContext

   這是由通用十進位算術規格定義的標準 context。精度設定為九。捨入設定
   為 "ROUND_HALF_EVEN"。所有旗標都被清除。沒有 trap 被啟用（因此在運
   算過程中不會引發例外）。

   因為 trap 被停用，這個 context 對於傾向於拿到 "NaN" 或 "Infinity"
   結果值而不是引發例外的應用程式很有用。這讓應用程式在存在原本會中止
   程式的條件時也能完成執行。

decimal.DefaultContext

   這個 context 被 "Context" 建構函式用作新 context 的原型。改變一個欄
   位（例如精度）的效果是改變 "Context" 建構函式建立的新 context 的預
   設值。

   這個 context 在多執行緒環境中最有用。在執行緒啟動之前改變其中一個欄
   位的效果是設定系統級預設值。不建議在執行緒啟動後改變欄位，因為這會
   需要執行緒同步來防止競爭條件。

   在單執行緒環境中，最好完全不使用這個 context。取而代之，只需按下面
   描述的方式明確建立 context。

   預設值為 "Context.prec"="28"、"Context.rounding"="ROUND_HALF_EVEN"
   ，並啟用 "Overflow"、"InvalidOperation" 和 "DivisionByZero" 的 trap
   。

除了這三個提供的 context 之外，還可以使用 "Context" 建構函式建立新的
context。

class decimal.Context(prec=None, rounding=None, Emin=None, Emax=None, capitals=None, clamp=None, flags=None, traps=None)

   建立一個新的 context。如果欄位未指定或為 "None"，則從
   "DefaultContext" 複製預設值。如果 *flags* 欄位未指定或為 "None"，則
   清除所有旗標。

   prec

      在 ["1", "MAX_PREC"] 範圍內的整數，用於設定 context 中算術運算的
      精度。

   rounding

      Rounding Modes 段落中列出的常數之一。

   traps
   flags

      要設定的任何訊號列表。一般來說，新 context 應該只設定 trap 並保
      持旗標清除。

   Emin
   Emax

      指定指數允許的外部限制的整數。*Emin* 必須在 ["MIN_EMIN"、"0"] 範
      圍內，*Emax* 在 ["0"、"MAX_EMAX"] 範圍內。

   capitals

      "0" 或 "1"（預設）。如果設定為 "1"，指數用大寫 "E" 列印；否則，
      使用小寫 "e"："Decimal('6.02e+23')"。

   clamp

      "0"（預設）或 "1"。如果設定為 "1"，在此 context 中可表示的
      "Decimal" 實例的指數 "e" 嚴格限制在 "Emin - prec + 1 <= e <=
      Emax - prec + 1" 範圍內。如果 *clamp* 為 "0"，則適用較弱的條件：
      "Decimal" 實例的調整指數最多為 "Emax"。當 *clamp* 為 "1" 時，如
      果可能的話，大的正規數字會減少其指數並在其係數上添加相應數量的零
      ，以符合指數約束；這保留了數字的值，但會失去有關有效尾隨零的資訊
      。例如：

         >>> Context(prec=6, Emax=999, clamp=1).create_decimal('1.23e999')
         Decimal('1.23000E+999')

      *clamp* 值為 "1" 可以與 IEEE 754 中指定的固定寬度十進位交換格式
      相容。

   "Context" 類別定義了幾個通用方法，以及大量在給定 context 中直接進行
   算術運算的方法。此外，對於上面描述的每個 "Decimal" 方法（除了
   "adjusted()" 和 "as_tuple()" 方法之外），都有相對應的 "Context" 方
   法。例如，對於 "Context" 實例 "C" 和 "Decimal" 實例 "x"，"C.exp(x)"
   等價於 "x.exp(context=C)"。每個 "Context" 方法在接受 Decimal 實例的
   任何地方都接受 Python 整數（"int" 的實例）。

   clear_flags()

      將所有旗標重設為 "0"。

   clear_traps()

      將所有 trap 重設為 "0"。

      在 3.3 版被加入.

   copy()

      回傳 context 的一個副本。

   copy_decimal(num, /)

      回傳 Decimal 實例 num 的副本。

   create_decimal(num='0', /)

      從 *num* 建立一個新的 Decimal 實例，但使用 *self* 作為 context。
      與 "Decimal" 建構函式不同，context 精度、捨入方法、旗標和 trap
      會套用於轉換。

      這很有用，因為常數通常會提供比應用程式需要的更高精度。另一個好處
      是捨入立即消除超出當前精度的數字的意外影響。在以下範例中，使用未
      捨入的輸入意味著在總和中加零可能會改變結果：

         >>> getcontext().prec = 3
         >>> Decimal('3.4445') + Decimal('1.0023')
         Decimal('4.45')
         >>> Decimal('3.4445') + Decimal(0) + Decimal('1.0023')
         Decimal('4.44')

      此方法實作了 IBM 規格的 to-number 操作。如果引數是字串，則不允許
      前導或尾隨的空白字元或底線。

   create_decimal_from_float(f, /)

      從浮點數 *f* 建立一個新的 Decimal 實例，但使用 *self* 作為
      context 進行四捨五入。與 "Decimal.from_float()" 類別方法不同，
      context 精度、捨入方法、旗標和 trap 會套用於轉換。

         >>> context = Context(prec=5, rounding=ROUND_DOWN)
         >>> context.create_decimal_from_float(math.pi)
         Decimal('3.1415')
         >>> context = Context(prec=5, traps=[Inexact])
         >>> context.create_decimal_from_float(math.pi)
         Traceback (most recent call last):
             ...
         decimal.Inexact: None

      在 3.1 版被加入.

   Etiny()

      回傳等於 "Emin - prec + 1" 的值，這是次正規結果的最小指數值。當
      發生下溢時，指數設定為 "Etiny"。

   Etop()

      回傳一個等於 "Emax - prec + 1" 的值。

   處理 decimal 的通常方法是建立 "Decimal" 實例，然後在活動執行緒的當
   前 context 中進行算術運算。另一種方法是使用 context 方法在特定
   context 中進行計算。這些方法與 "Decimal" 類別的方法相似，在此僅簡要
   重述。

   abs(x, /)

      回傳 *x* 的絕對值。

   add(x, y, /)

      回傳 *x* 與 *y* 的和。

   canonical(x, /)

      回傳相同的 Decimal 物件 *x*。

   compare(x, y, /)

      數值比較 *x* 和 *y*。

   compare_signal(x, y, /)

      數值比較兩個運算元的值。

   compare_total(x, y, /)

      使用兩個運算元的抽象表示法進行比較。

   compare_total_mag(x, y, /)

      使用兩個運算元的抽象表示法進行比較，忽略符號。

   copy_abs(x, /)

      回傳 *x* 的副本，將符號設定為 0。

   copy_negate(x, /)

      回傳 *x* 的副本，將符號反轉。

   copy_sign(x, y, /)

      將 *y* 的正負號複製到 *x*。

   divide(x, y, /)

      回傳 *x* 除以 *y*。

   divide_int(x, y, /)

      回傳 *x* 除以 *y*，截斷為整數。

   divmod(x, y, /)

      將兩個數相除並回傳結果的整數部分。

   exp(x, /)

      回傳 "e ** x"。

   fma(x, y, z, /)

      回傳 *x* 乘以 *y*，再加上 *z*。

   is_canonical(x, /)

      如果 *x* 是標準形式則回傳 "True"；否則回傳 "False"。

   is_finite(x, /)

      如果 *x* 是有限的則回傳 "True"；否則回傳 "False"。

   is_infinite(x, /)

      如果 *x* 是無限大則回傳 "True"；否則回傳 "False"。

   is_nan(x, /)

      如果 *x* 是 qNaN 或 sNaN 則回傳 "True"；否則回傳 "False"。

   is_normal(x, /)

      如果 *x* 是正規數 (normal number) 則回傳 "True"；否則回傳
      "False"。

   is_qnan(x, /)

      如果 *x* 是安靜型 NaN (quiet NaN) 則回傳 "True"；否則回傳
      "False"。

   is_signed(x, /)

      如果 *x* 是負數則回傳 "True"；否則回傳 "False"。

   is_snan(x, /)

      如果 *x* 是訊號型 NaN (signaling NaN) 則回傳 "True"；否則回傳
      "False"。

   is_subnormal(x, /)

      如果 *x* 是次正規數 (subnormal) 則回傳 "True"；否則回傳 "False"
      。

   is_zero(x, /)

      如果 *x* 是零則回傳 "True"；否則回傳 "False"。

   ln(x, /)

      回傳 *x* 的自然對數（以 e 為底）。

   log10(x, /)

      回傳 *x* 的以 10 為底的對數。

   logb(x, /)

      回傳運算元最高有效位數（MSD）數值的指數。

   logical_and(x, y, /)

      將每個運算元的位數套用邏輯運算 *and*。

   logical_invert(x, /)

      反轉 *x* 中的所有數字。

   logical_or(x, y, /)

      在每個運算元的數字之間套用邏輯運算 *or*。

   logical_xor(x, y, /)

      在每個運算元的數字之間套用邏輯運算 *xor*。

   max(x, y, /)

      數值比較兩個值並回傳最大值。

   max_mag(x, y, /)

      數值比較值，忽略其符號。

   min(x, y, /)

      數值比較兩個值並回傳最小值。

   min_mag(x, y, /)

      數值比較值，忽略其符號。

   minus(x, /)

      Minus 對應於 Python 中的一元前綴減號運算子。

   multiply(x, y, /)

      回傳 *x* 和 *y* 的乘積。

   next_minus(x, /)

      回傳小於 *x* 的最大可表示數字。

   next_plus(x, /)

      回傳大於 *x* 的最小可表示數字。

   next_toward(x, y, /)

      回傳最接近 *x* 的數字，方向指向 *y*。

   normalize(x, /)

      將 *x* 簡化為最簡形式。

   number_class(x, /)

      回傳 *x* 類別的指示。

   plus(x, /)

      Plus 對應於 Python 中的一元前綴加號運算子。此運算會套用 context
      精度和捨入，因此它 *不是* 一個恆等運算。

   power(x, y, modulo=None)

      回傳 "x" 的 "y" 次方；如果有提供 "modulo"，則回傳對 "modulo" 取
      模後的結果。

      使用兩個引數計算 "x**y"。如果 "x" 是負數，則 "y" 必須是整數。除
      非 "y" 是整數且結果是有限的且可以在「精度」位數中精確表示，否則
      結果將是不精確的。使用 context 的捨入模式。在 Python 版本中，結
      果總是正確捨入的。

      "Decimal(0) ** Decimal(0)" 會導致 "InvalidOperation"，如果
      "InvalidOperation" 沒有被捕捉，則會產生 "Decimal('NaN')"。

      在 3.3 版的變更: C 模組以正確捨入的 "exp()" 和 "ln()" 函式來計算
      "power()"。結果是明確定義的，但僅「幾乎總是正確捨入」。

      使用三個引數計算 "(x**y) % modulo"。對於三個引數的形式，引數有以
      下限制：

      * 所有三個引數必須是整數

      * "y" 必須是非負數

      * "x" 或 "y" 中至少一個必須是非零

      * "modulo" 必須是非零且最多有「精度」位數

      "Context.power(x, y, modulo)" 的結果值等於以無限精度計算 "(x**y)
      % modulo" 所得到的值，但計算更加高效。結果的指數是零，無論 "x"、
      "y" 和 "modulo" 的指數如何。結果總是精確的。

   quantize(x, y, /)

      回傳等於 *x*（捨入後）的值，具有 *y* 的指數。

   radix()

      只回傳 10，因為這是 Decimal :)

   remainder(x, y, /)

      回傳整數除法的餘數。

      結果的符號（如果非零）與原始被除數的符號相同。

   remainder_near(x, y, /)

      回傳 "x - y * n"，其中 *n* 是最接近 "x / y" 精確值的整數（如果結
      果是 0，則其符號將是 *x* 的符號）。

   rotate(x, y, /)

      回傳 *x* 的旋轉副本，旋轉 *y* 次。

   same_quantum(x, y, /)

      如果兩個運算元有相同的指數則回傳 "True"。

   scaleb(x, y, /)

      回傳第一個運算元在加上第二個值的 exp 後的結果。

   shift(x, y, /)

      回傳 *x* 的移位副本，移位 *y* 次。

   sqrt(x, /)

      非負數在 context 精度下的平方根。

   subtract(x, y, /)

      回傳 *x* 和 *y* 的差。

   to_eng_string(x, /)

      轉換為字串，如果需要指數則使用工程記號。

      工程記號的指數是 3 的倍數。這可能在小數點左側留下最多 3 位數字，
      並可能需要添加一個或兩個尾隨零。

   to_integral_exact(x, /)

      捨入為整數。

   to_sci_string(x, /)

      使用科學記號法將數字轉換為字串。


常數
====

decimal.SPEC_VERSION

   The highest version of the General Decimal Arithmetic Specification
   that this implementation complies with. See
   https://speleotrove.com/decimal/decarith.html for the
   specification.

   在 3.15 版被加入.

The following constants are only relevant for the C module. They are
also included in the pure Python version for compatibility.

+-----------------------------------+-----------------------+---------------------------------+
|                                   | 32 位元               | 64 位元                         |
|===================================|=======================|=================================|
| decimal.MAX_PREC                  | "425000000"           | "999999999999999999"            |
+-----------------------------------+-----------------------+---------------------------------+
| decimal.MAX_EMAX                  | "425000000"           | "999999999999999999"            |
+-----------------------------------+-----------------------+---------------------------------+
| decimal.MIN_EMIN                  | "-425000000"          | "-999999999999999999"           |
+-----------------------------------+-----------------------+---------------------------------+
| decimal.MIN_ETINY                 | "-849999999"          | "-1999999999999999997"          |
+-----------------------------------+-----------------------+---------------------------------+
| decimal.IEEE_CONTEXT_MAX_BITS     | "256"                 | "512"                           |
+-----------------------------------+-----------------------+---------------------------------+

decimal.HAVE_THREADS

   值是 "True"。已棄用，因為 Python 現在總是有執行緒。

   在 3.9 版之後被棄用.

decimal.HAVE_CONTEXTVAR

   預設值是 "True"。如果 Python 是使用 "--without-decimal-contextvar
   選項" 配置的，C 版本使用執行緒區域而非協程區域 context，且值為
   "False"。在某些巢狀 context 情境中這稍微快一些。

   在 3.8.3 版被加入.


捨入模式
========

decimal.ROUND_CEILING

   向 "Infinity" 捨入。

decimal.ROUND_DOWN

   向零捨入。

decimal.ROUND_FLOOR

   向 "-Infinity" 捨入。

decimal.ROUND_HALF_DOWN

   捨入到最近值，平局時向零捨入。

decimal.ROUND_HALF_EVEN

   捨入到最近值，平局時向最近的偶數捨入。

decimal.ROUND_HALF_UP

   捨入到最近值，平局時遠離零捨入。

decimal.ROUND_UP

   遠離零捨入。

decimal.ROUND_05UP

   如果向零捨入後的最後一位數字為 0 或 5，則遠離零捨入；否則向零捨入。


訊號
====

訊號代表在計算過程中產生的條件。每個訊號對應一個情境旗標和一個情境陷阱
啟用器。

每當遇到條件時，情境旗標就會被設定。計算後，可以檢查旗標以獲取資訊（例
如，確定計算是否精確）。檢查旗標後，請確保在開始下一次計算之前清除所有
旗標。

如果為訊號設定了情境的陷阱啟用器，那麼條件會導致引發 Python 例外。例如
，如果設定了 "DivisionByZero" 陷阱，那麼在遇到條件時會引發
"DivisionByZero" 例外。

class decimal.Clamped

   更改指數以符合表示限制。

   通常，當指數超出情境的 "Emin" 和 "Emax" 限制時，會發生夾制。如果可
   能的話，透過在係數中新增零來縮小指數以符合限制。

class decimal.DecimalException

   其他訊號的基底類別，也是 "ArithmeticError" 的子類別。

class decimal.DivisionByZero

   發出非無限數被零除的訊號。

   可能發生在除法、模除法或將數字提升到負次方時。如果此訊號未被捕捉，
   回傳 "Infinity" 或 "-Infinity"，符號由計算的輸入決定。

class decimal.Inexact

   指示發生了捨入且結果不精確。

   當捨入過程中丟棄非零數字時發出訊號。回傳捨入結果。訊號旗標或陷阱用
   於檢測結果何時不精確。

class decimal.InvalidOperation

   執行了無效的運算。

   指示請求了不合理的運算。如果未被捕捉，回傳 "NaN"。可能的原因包括：

      Infinity - Infinity
      0 * Infinity
      Infinity / Infinity
      x % 0
      Infinity % x
      sqrt(-x) and x > 0
      0 ** 0
      x ** (non-integer)
      x ** Infinity

class decimal.Overflow

   數值溢位。

   指示在捨入發生後指數大於 "Context.Emax"。如果未被捕捉，結果取決於捨
   入模式，要麼向內拉到最大可表示的有限數，要麼向外捨入到 "Infinity"。
   在任何情況下，"Inexact" 和 "Rounded" 也會發出訊號。

class decimal.Rounded

   發生了捨入，但可能沒有遺失資訊。

   當捨入丟棄數字時發出訊號；即使這些數字是零（例如將 "5.00" 捨入為
   "5.0"）。如果沒有被捕捉，則回傳不變的結果。此訊號用於檢測有效數字的
   遺失。

class decimal.Subnormal

   在捨入之前指數低於 "Emin"。

   當運算結果是次正規（指數太小）時發生。如果沒有被捕捉，則回傳不變的
   結果。

class decimal.Underflow

   數值下溢，結果捨入為零。

   當次正規結果被捨入推向零時發生。"Inexact" 和 "Subnormal" 也會發出訊
   號。

class decimal.FloatOperation

   啟用混合 float 和 Decimal 的更嚴格語意。

   如果訊號沒有被捕捉（預設），則在 "Decimal" 建構函式、
   "create_decimal()" 和所有比較運算子中允許混合 float 和 Decimal。轉
   換和比較都是精確的。任何混合運算的發生都會透過在 context 旗標中設定
   "FloatOperation" 來默默記錄。使用 "from_float()" 或
   "create_decimal_from_float()" 的明確轉換不會設定標誌。

   否則（訊號被捕捉），只有相等比較和明確轉換是安靜的。所有其他混合運
   算都會引發 "FloatOperation"。

以下表格總結了訊號的階層結構：

   exceptions.ArithmeticError(exceptions.Exception)
       DecimalException
           Clamped
           DivisionByZero(DecimalException, exceptions.ZeroDivisionError)
           Inexact
               Overflow(Inexact, Rounded)
               Underflow(Inexact, Rounded, Subnormal)
           InvalidOperation
           Rounded
           Subnormal
           FloatOperation(DecimalException, exceptions.TypeError)


浮點數注意事項
==============


透過增加精度來減輕捨入誤差
--------------------------

使用十進位浮點數消除了十進位表示誤差（使得可以精確表示 "0.1"）；然而，
當非零數字超過固定精度時，某些運算仍然可能產生捨入誤差。

捨入誤差的影響可能會因為幾乎抵消的數量的加法或減法而被放大，導致有效位
數的損失。Knuth 提供了兩個教學範例，其中精度不足的捨入浮點運算導致加法
的結合律和分配律失效：

   # 來自 Seminumerical Algorithms 第 4.2.2 節的範例。
   >>> from decimal import Decimal, getcontext
   >>> getcontext().prec = 8

   >>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
   >>> (u + v) + w
   Decimal('9.5111111')
   >>> u + (v + w)
   Decimal('10')

   >>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
   >>> (u*v) + (u*w)
   Decimal('0.01')
   >>> u * (v+w)
   Decimal('0.0060000')

"decimal" 模組使得透過充分擴展精度來避免有效位數損失，從而恢復恆等式成
為可能：

   >>> getcontext().prec = 20
   >>> u, v, w = Decimal(11111113), Decimal(-11111111), Decimal('7.51111111')
   >>> (u + v) + w
   Decimal('9.51111111')
   >>> u + (v + w)
   Decimal('9.51111111')
   >>>
   >>> u, v, w = Decimal(20000), Decimal(-6), Decimal('6.0000003')
   >>> (u*v) + (u*w)
   Decimal('0.0060000')
   >>> u * (v+w)
   Decimal('0.0060000')


特殊值
------

"decimal" 模組的數字系統提供特殊值，包括 "NaN"、"sNaN"、"-Infinity"、
"Infinity" 以及兩個零 "+0" 和 "-0"。

無窮大可以直接透過 "Decimal('Infinity')" 建構。此外，當
"DivisionByZero" 訊號未被捕捉時，它們可能來自被零除。同樣地，當
"Overflow" 訊號未被捕捉時，無窮大可能來自超出最大可表示數字限制的捨入
。

無窮大是有符號的（仿射）並且可以用於算術運算，在那裡它們被視為非常大的
不確定數字。例如，將常數加到無窮大會得到另一個無限結果。

某些運算是不確定的且會回傳 "NaN"，或者如果 "InvalidOperation" 訊號被捕
捉，則會引發例外。例如，"0/0" 會回傳 "NaN"，意思是「非數字」。這種
"NaN" 是安靜的，一旦建立，會流經其他計算且總是產生另一個 "NaN"。這種行
為對於偶爾有缺失輸入的一系列計算很有用——它允許計算繼續進行，同時將特定
結果標記為無效。

一個變體是 "sNaN"，它在每次運算後發出訊號而不是保持安靜。當無效結果需
要中斷計算進行特殊處理時，這是一個有用的回傳值。

當涉及 "NaN" 時，Python 比較運算子的行為可能有點令人驚訝。當其中一個運
算元是安靜或發出訊號的 "NaN" 時，相等性測試總是回傳 "False`（即使在執
行 ``Decimal('NaN')==Decimal('NaN')`" 時也是如此），而不等性測試總是回
傳 "True"。嘗試使用任何 "<"、"<="、">" 或 ">=" 運算子比較兩個 Decimal
時，如果任一運算元是 "NaN"，將引發 "InvalidOperation" 訊號，如果此訊號
沒有被捕捉則回傳 "False"。請注意，通用十進位算術規格沒有指定直接比較的
行為；這些涉及 "NaN" 比較的規則取自 IEEE 854 標準（參見第 5.7 節的表 3
）。為確保嚴格符合標準，請改用 "compare()" 和 "compare_signal()" 方法
。

帶符號的零可能來自下溢計算。它們保持如果計算以更高精度執行所會產生的符
號。由於它們的大小是零，正零和負零都被視為相等，它們的符號是資訊性的。

除了兩個不同但相等的帶符號零之外，還有各種零的表示方式，它們有不同的精
度但值相等。這需要一點時間來適應。對於習慣於標準化浮點表示的眼睛來說，
以下計算回傳等於零的值並不立即明顯：

>>> 1 / Decimal('Infinity')
Decimal('0E-1000026')


與執行緒協作
============

"getcontext()" 函式為每個執行緒存取不同的 "Context" 物件。擁有獨立的執
行緒情境意味著執行緒可以進行變更（如 "getcontext().prec=10"）而不會干
擾其他執行緒。

同樣地，"setcontext()" 函式會自動將其目標指派給目前執行緒。

如果在 "getcontext()" 之前沒有呼叫 "setcontext()"，則 "getcontext()"
會自動建立新的 context 供目前執行緒使用。新的 context 物件的預設值取自
"decimal.DefaultContext" 物件。

"sys.flags.thread_inherit_context" 旗標會影響新執行緒的 context。如果
該旗標為 false，新執行緒會以空的 context 啟動。在這種情況下，
"getcontext()" 在被呼叫時會建立新的 context 物件，並使用
*DefaultContext* 的預設值。如果該旗標為 true，新執行緒會以呼叫
"threading.Thread.start()" 的執行緒的 context 副本啟動。

要控制預設值以便每個執行緒在整個應用程式中使用相同的值，請直接修改
*DefaultContext* 物件。這應該在任何執行緒啟動*之前*完成，這樣執行緒呼
叫 "getcontext()" 時就不會有競爭條件。例如：

   # 為即將啟動的所有執行緒設定應用程式範圍的預設值
   DefaultContext.prec = 12
   DefaultContext.rounding = ROUND_DOWN
   DefaultContext.traps = ExtendedContext.traps.copy()
   DefaultContext.traps[InvalidOperation] = 1
   setcontext(DefaultContext)

   # 之後，可以啟動執行緒
   t1.start()
   t2.start()
   t3.start()
    . . .


實用範例
========

以下是一些實用範例，作為工具函式並展示與 "Decimal" 類別協作的方法：

   def moneyfmt(value, places=2, curr='', sep=',', dp='.',
                pos='', neg='-', trailneg=''):
       """將 Decimal 轉換為貨幣格式的字串。

       places:  小數點後所需的位數
       curr:    符號前的選擇性貨幣符號（可為空白）
       sep:     選擇性的分組分隔符號（逗號、句號、空格或空白）
       dp:      小數點指示符號（逗號或句號）
                僅在 places 為零時指定為空白
       pos:     正數的選擇性符號：'+'、空格或空白
       neg:     負數的選擇性符號：'-'、'('、空格或空白
       trailneg:選擇性的尾隨負號指示符號：'-'、')'、空格或空白

       >>> d = Decimal('-1234567.8901')
       >>> moneyfmt(d, curr='$')
       '-$1,234,567.89'
       >>> moneyfmt(d, places=0, sep='.', dp='', neg='', trailneg='-')
       '1.234.568-'
       >>> moneyfmt(d, curr='$', neg='(', trailneg=')')
       '($1,234,567.89)'
       >>> moneyfmt(Decimal(123456789), sep=' ')
       '123 456 789.00'
       >>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>')
       '<0.02>'

       """
       q = Decimal(10) ** -places      # 2 個位數 --> '0.01'
       sign, digits, exp = value.quantize(q).as_tuple()
       result = []
       digits = list(map(str, digits))
       build, next = result.append, digits.pop
       if sign:
           build(trailneg)
       for i in range(places):
           build(next() if digits else '0')
       if places:
           build(dp)
       if not digits:
           build('0')
       i = 0
       while digits:
           build(next())
           i += 1
           if i == 3 and digits:
               i = 0
               build(sep)
       build(curr)
       build(neg if sign else pos)
       return ''.join(reversed(result))

   def pi():
       """計算 Pi 到目前的精度。

       >>> print(pi())
       3.141592653589793238462643383

       """
       getcontext().prec += 2  # 中間步驟的額外位數
       three = Decimal(3)      # 用 "three=3.0" 替換為一般浮點數
       lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
       while s != lasts:
           lasts = s
           n, na = n+na, na+8
           d, da = d+da, da+32
           t = (t * n) / d
           s += t
       getcontext().prec -= 2
       return +s               # 一元正號套用新的精度

   def exp(x):
       """回傳 e 的 x 次方。結果型別與輸入型別相同。

       >>> print(exp(Decimal(1)))
       2.718281828459045235360287471
       >>> print(exp(Decimal(2)))
       7.389056098930650227230427461
       >>> print(exp(2.0))
       7.38905609893
       >>> print(exp(2+0j))
       (7.38905609893+0j)

       """
       getcontext().prec += 2
       i, lasts, s, fact, num = 0, 0, 1, 1, 1
       while s != lasts:
           lasts = s
           i += 1
           fact *= i
           num *= x
           s += num / fact
       getcontext().prec -= 2
       return +s

   def cos(x):
       """回傳以弧度為單位的 x 的餘弦值。

       泰勒級數近似在 x 值較小時效果最佳。
       對於較大的值，先計算 x = x % (2 * pi)。

       >>> print(cos(Decimal('0.5')))
       0.8775825618903727161162815826
       >>> print(cos(0.5))
       0.87758256189
       >>> print(cos(0.5+0j))
       (0.87758256189+0j)

       """
       getcontext().prec += 2
       i, lasts, s, fact, num, sign = 0, 0, 1, 1, 1, 1
       while s != lasts:
           lasts = s
           i += 2
           fact *= i * (i-1)
           num *= x * x
           sign *= -1
           s += num / fact * sign
       getcontext().prec -= 2
       return +s

   def sin(x):
       """回傳以弧度為單位的 x 的正弦值。

       泰勒級數近似在 x 值較小時效果最佳。
       對於較大的值，先計算 x = x % (2 * pi)。

       >>> print(sin(Decimal('0.5')))
       0.4794255386042030002732879352
       >>> print(sin(0.5))
       0.479425538604
       >>> print(sin(0.5+0j))
       (0.479425538604+0j)

       """
       getcontext().prec += 2
       i, lasts, s, fact, num, sign = 1, 0, x, 1, x, 1
       while s != lasts:
           lasts = s
           i += 2
           fact *= i * (i-1)
           num *= x * x
           sign *= -1
           s += num / fact * sign
       getcontext().prec -= 2
       return +s


Decimal 常見問題
================

問：輸入 "decimal.Decimal('1234.5')" 很麻煩。在使用互動式直譯器時，有
沒有辦法減少輸入？

答：有些使用者會將建構式縮寫為單一字母：

>>> D = decimal.Decimal
>>> D('1.23') + D('3.45')
Decimal('4.68')

問：在一個有兩位小數的定點應用程式中，有些輸入有很多位數需要被捨入。其
他輸入不應該有多餘的位數，需要被驗證。應該使用什麼方法？

答："quantize()" 方法會捨入到固定的小數位數。如果設定了 "Inexact" 陷阱
，它也可用於驗證：

>>> TWOPLACES = Decimal(10) ** -2       # same as Decimal('0.01')

>>> # Round to two places
>>> Decimal('3.214').quantize(TWOPLACES)
Decimal('3.21')

>>> # Validate that a number does not exceed two places
>>> Decimal('3.21').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Decimal('3.21')

>>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Traceback (most recent call last):
   ...
Inexact: None

問：一旦我有了有效的兩位小數輸入，如何在整個應用程式中維持這個不變式？

答：某些運算如加法、減法和整數乘法會自動保留定點。其他運算，例如除法和
非整數乘法，會改變小數位數，需要接著執行 "quantize()" 步驟：

>>> a = Decimal('102.72')           # Initial fixed-point values
>>> b = Decimal('3.17')
>>> a + b                           # Addition preserves fixed-point
Decimal('105.89')
>>> a - b
Decimal('99.55')
>>> a * 42                          # So does integer multiplication
Decimal('4314.24')
>>> (a * b).quantize(TWOPLACES)     # Must quantize non-integer multiplication
Decimal('325.62')
>>> (b / a).quantize(TWOPLACES)     # And quantize division
Decimal('0.03')

在開發定點應用程式時，定義函式來處理 "quantize()" 步驟很方便：

>>> def mul(x, y, fp=TWOPLACES):
...     return (x * y).quantize(fp)
...
>>> def div(x, y, fp=TWOPLACES):
...     return (x / y).quantize(fp)

>>> mul(a, b)                       # Automatically preserve fixed-point
Decimal('325.62')
>>> div(b, a)
Decimal('0.03')

問：有很多方式可以表達相同的值。數字 "200"、"200.000"、"2E2" 和
".02E+4" 在不同精度下都有相同的值。有沒有辦法將它們轉換為單一可識別的
標準值？

答："normalize()" 方法會將所有等價的值對映到單一代表值：

>>> values = map(Decimal, '200 200.000 2E2 .02E+4'.split())
>>> [v.normalize() for v in values]
[Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2'), Decimal('2E+2')]

問：在計算中何時會發生捨入？

答：它發生在計算*之後*。decimal 規格的哲學是數字被視為精確的，且獨立於
目前的 context 建立。它們甚至可以有比目前 context 更高的精度。計算使用
那些精確的輸入進行處理，然後捨入（或其他 context 運算）被套用到計算的*
結果*上：

   >>> getcontext().prec = 5
   >>> pi = Decimal('3.1415926535')   # 超過 5 位數
   >>> pi                             # 保留所有數字
   Decimal('3.1415926535')
   >>> pi + 0                         # 加法後捨入
   Decimal('3.1416')
   >>> pi - Decimal('0.00005')        # 減去未捨入的數字，然後捨入
   Decimal('3.1415')
   >>> pi + 0 - Decimal('0.00005').   # 中間值被捨入
   Decimal('3.1416')

問：有些 decimal 值總是以指數表示法印出。有沒有辦法得到非指數表示法？

答：對於某些值，指數表示法是表達係數中有效位數的唯一方式。例如，將
"5.0E+3" 表示為 "5000" 保持了值不變，但無法顯示原始值的兩位有效性。

如果應用程式不關心追蹤有效性，很容易移除指數和尾隨零，遺失有效性，但保
持值不變：

>>> def remove_exponent(d):
...     return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()

>>> remove_exponent(Decimal('5E+3'))
Decimal('5000')

問：有沒有辦法將一般的 float 轉換為 "Decimal"？

答：是的，任何二進位浮點數都可以精確地表示為 Decimal，儘管精確轉換可能
需要比直覺所預期的更高精度：

   >>> Decimal(math.pi)
   Decimal('3.141592653589793115997963468544185161590576171875')

問：在複雜計算中，如何確保我沒有因為精度不足或捨入異常而得到虛假的結果
？

答：decimal 模組使測試結果變得容易。最佳實踐是使用更高的精度和各種捨入
模式重新執行計算。結果差異很大表示精度不足、捨入模式問題、病態輸入或數
值不穩定的演算法。

問：我注意到 context 精度被套用到運算的結果上，但不套用到輸入上。在混
合不同精度的值時，有什麼需要注意的嗎？

答：是的。原則是所有值都被視為精確的，對這些值的算術也是如此。只有結果
會被捨入。對於輸入的好處是「你輸入什麼就得到什麼」。缺點是如果你忘記輸
入沒有被捨入，結果可能看起來很奇怪：

   >>> getcontext().prec = 3
   >>> Decimal('3.104') + Decimal('2.104')
   Decimal('5.21')
   >>> Decimal('3.104') + Decimal('0.000') + Decimal('2.104')
   Decimal('5.20')

解決方案是增加精度或使用一元加號運算強制輸入捨入：

   >>> getcontext().prec = 3
   >>> +Decimal('1.23456789')      # 一元正號觸發捨入
   Decimal('1.23')

或者，可以使用 "Context.create_decimal()" 方法在建立時將輸入捨入：

>>> Context(prec=5, rounding=ROUND_DOWN).create_decimal('1.2345678')
Decimal('1.2345')

問：CPython 實作對大數運算快嗎？

答：是的。在 CPython 和 PyPy3 實作中，decimal 模組的 C/CFFI 版本整合了
高速 libmpdec 函式庫，用於任意精度正確捨入的十進位浮點運算 [1]。
"libmpdec" 對中等大小的數字使用 Karatsuba 乘法，對非常大的數字使用數論
轉換。

context 必須適應精確的任意精度運算。"Emin" 和 "Emax" 應該始終設定為最
大值，"clamp" 應該始終為 0（預設）。設定 "prec" 需要一些小心。

嘗試大數運算的最簡單方法是同時使用 "prec" 的最大值 [2]：

   >>> setcontext(Context(prec=MAX_PREC, Emax=MAX_EMAX, Emin=MIN_EMIN))
   >>> x = Decimal(2) ** 256
   >>> x / 128
   Decimal('904625697166532776746648320380374280103671755200316906558262375061821325312')

對於不精確的結果，"MAX_PREC" 在 64 位元平台上太大了，可用記憶體將不足
：

   >>> Decimal(1) / 3
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   MemoryError

在具有過度分配的系統上（例如 Linux），更精密的方法是將 "prec" 調整為可
用 RAM 的數量。假設你有 8GB 的 RAM，並且預期 10 個同時操作數，每個最多
使用 500MB：

   >>> import sys
   >>>
   >>> # 使用 8 位元組字組中 500MB 的單一操作數最大位數
   >>> # 每個字組 19 位數（32 位元組建中為 4 位元組和 9 位數）：
   >>> maxdigits = 19 * ((500 * 1024**2) // 8)
   >>>
   >>> # 檢查這是否有效：
   >>> c = Context(prec=maxdigits, Emax=MAX_EMAX, Emin=MIN_EMIN)
   >>> c.traps[Inexact] = True
   >>> setcontext(c)
   >>>
   >>> # 用九填滿可用的精度：
   >>> x = Decimal(0).logical_invert() * 9
   >>> sys.getsizeof(x)
   524288112
   >>> x + 2
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
     decimal.Inexact: [<class 'decimal.Inexact'>]

一般來說（特別是在沒有過度分配的系統上），建議估算更緊密的界限並設定
"Inexact" trap，如果所有計算都預期是精確的。

[1] 在 3.3 版被加入.

[2] 在 3.9 版的變更: 這個方法現在對所有精確結果都有效，除了非整數冪次
    。
