decimal --- حساب دهدهی ممیز ثابت و ممیز شناور

کد منبع: Lib/decimal.py


ماژول decimal پشتیبانی از محاسبات ممیز شناور اعشاری سریع و با گرد کردن صحیح را فراهم می‌کند. این ماژول چندین مزیت نسبت به نوع داده float دارد:

  • Decimal «بر اساس یک مدل ممیز شناور است که با در نظر گرفتن انسان‌ها طراحی شده و لزوماً دارای یک اصل راهنمای برتر است -- رایانه‌ها باید حسابی فراهم کنند که به همان شیوه‌ای کار کند که حسابی که مردم در مدرسه می‌آموزند، کار می‌کند.» -- گزیده‌ای از مشخصات حساب اعشاری.

  • اعداد دهدهی را می‌توان به‌صورت دقیق بازنمایی کرد. در مقابل، اعدادی مانند 1.1 و 2.2 بازنمایی دقیقی در ممیز شناور دودویی ندارند. کاربران نهایی معمولاً انتظار ندارند 1.1 + 2.2 به‌صورت 3.3000000000000003 نمایش داده شود، همان‌گونه که در ممیز شناور دودویی رخ می‌دهد.

  • این دقت در محاسبات حسابی نیز برقرار است. در ممیز شناور اعشاری، 0.1 + 0.1 + 0.1 - 0.3 دقیقاً برابر با صفر است. در ممیز شناور دودویی، نتیجه 5.5511151231257827e-017 است. هرچند به صفر نزدیک است، اما این تفاوت‌ها مانع از بررسی برابری قابل‌اعتماد می‌شوند و ممکن است انباشته شوند. به همین دلیل، ممیز شناور اعشاری در برنامه‌های حسابداری که دارای ناورداهای برابری دقیق هستند، ترجیح داده می‌شود.

  • ماژول decimal مفهوم ارقام معنادار را در بر می‌گیرد، به‌طوری‌که 1.30 + 1.20 برابر 2.50 است. صفر پایانی برای نشان دادن معناداری حفظ می‌شود. این نمایش مرسوم برای کاربردهای مالی است. برای ضرب، روش «کتاب درسی» از تمام ارقام عوامل ضرب استفاده می‌کند. برای مثال، 1.3 * 1.2 مقدار 1.56 را می‌دهد، در حالی که 1.30 * 1.20 مقدار 1.5600 را می‌دهد.

  • برخلاف ممیز شناور دودویی مبتنی بر سخت‌افزار، ماژول decimal دارای دقت قابل تغییر توسط کاربر (با پیش‌فرض ۲۸ رقم اعشار) است که می‌تواند به هر اندازه‌ای که برای یک مسئله مشخص لازم باشد، بزرگ باشد:

    >>> 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 طراحی شده است تا «بدون جانبداری، هم از حساب اعشاری دقیق و بدون گرد کردن (که گاهی حساب ممیز ثابت نامیده می‌شود) و هم از حساب ممیز شناور گردشده» پشتیبانی کند. — گزیده‌ای از مشخصات حساب اعشاری.

طراحی ماژول بر سه مفهوم متمرکز است: عدد اعشاری، زمینه محاسبات، و سیگنال‌ها.

یک عدد ده‌دهی تغییرناپذیر است. این عدد دارای علامت، ارقام ضریب و توان است. برای حفظ معناداری، صفرهای انتهایی از ارقام ضریب حذف نمی‌شوند. اعداد ده‌دهی همچنین شامل مقادیر خاصی مانند 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.

برای هر سیگنال، یک پرچم و یک فعال‌ساز تله وجود دارد. هنگامی که یک سیگنال رخ می‌دهد، پرچم آن روی ۱ تنظیم می‌شود؛ سپس اگر فعال‌ساز تله روی ۱ تنظیم شده باشد، یک استثنا پرتاب می‌شود. پرچم‌ها پایا هستند، بنابراین کاربر باید پیش از پایش یک محاسبه، آن‌ها را بازنشانی کند.

همچنین ملاحظه نمائید

آموزش شروع سریع

آغاز معمول استفاده از اعداد اعشاری، ایمپورت کردن ماژول، مشاهده‌ی زمینه‌ی فعلی با 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       # Set a new precision

نمونه‌های Decimal را می‌توان از اعداد صحیح، رشته‌ها، اعداد اعشاری یا تاپل‌ها ساخت. ساخت از یک عدد صحیح یا عدد اعشاری، تبدیل دقیق مقدار آن عدد صحیح یا عدد اعشاری را انجام می‌دهد. اعداد Decimal شامل مقادیر ویژه‌ای مانند NaN هستند که مخفف «Not a number» است، همچنین 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.

دسیمال‌ها با بسیاری از بخش‌های دیگر پایتون به‌خوبی تعامل می‌کنند. در اینجا یک سیرک پرنده کوچک ممیز شناور دسیمال آمده است:

>>> 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')

دسیمال‌ها را می‌توان (با تابع توکار format() یا اف‌استرینگ‌ها) به‌صورت نماد ممیز ثابت یا علمی قالب‌بندی کرد، با استفاده از همان سینتکس قالب‌بندی (مراجعه کنید به زبان کوچک مشخصات قالب‌بندی) که نوع توکار float دارد:

>>> 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() مفید باشد. برای فعال کردن یک زمینه جایگزین، از تابع setcontext() استفاده کنید.

مطابق با استاندارد، ماژول decimal دو زمینه استاندارد آماده استفاده، 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 نشان می‌دهد که تقریب گویای عدد پی گرد شده است (ارقام فراتر از دقت زمینه دور ریخته شدند) و نتیجه نادقیق است (برخی از ارقام دور ریخته‌شده غیرصفر بودند).

تله‌های منفرد با استفاده از دیکشنری موجود در ویژگی 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

بیشتر برنامه‌ها زمینه‌ی جاری را تنها یک بار، در آغاز برنامه تنظیم می‌کنند. و در بسیاری از برنامه‌های کاربردی، داده‌ها درون یک حلقه با یک تبدیل (cast) واحد به Decimal تبدیل می‌شوند. پس از تنظیم زمینه و ایجاد مقادیر Decimal، بخش عمده‌ی برنامه داده‌ها را دقیقاً مانند سایر انواع عددی پایتون دستکاری می‌کند.

اشیای Decimal

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

یک شیء جدید Decimal بر اساس value بسازید.

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 در بالا آمده است، مجاز هستند. این موارد شامل ارقام دهدهی از الفباهای مختلف دیگر (برای مثال، ارقام عربی-هندی و دوناگری) به‌همراه ارقام تمام‌عرض '\uff10' تا '\uff19' می‌شوند. بزرگی و کوچکی حروف اهمیت ندارد، بنابراین، برای مثال، inf، Inf، INFINITY و iNfINity همگی نگارش‌های قابل‌قبول برای بی‌نهایت مثبت هستند.

اگر value یک tuple باشد، باید سه کامپوننت داشته باشد: یک علامت (0 برای مثبت یا 1 برای منفی)، یک tuple از ارقام، و یک توان عدد صحیح. برای مثال، Decimal((0, (1, 4, 1, 4), -3)) Decimal('1.414') را برمی‌گرداند.

اگر value یک float باشد، مقدار ممیز شناور دودویی بدون از دست دادن دقت به معادل دهدهی دقیق خود تبدیل می‌شود. این تبدیل اغلب ممکن است به ۵۳ رقم دقت یا بیشتر نیاز داشته باشد. برای مثال، Decimal(float('1.1')) به Decimal('1.100000000000000088817841970012523233890533447265625') تبدیل می‌شود.

دقت زمینه بر تعداد ارقام ذخیره‌شده تأثیر نمی‌گذارد. این موضوع منحصراً بر اساس تعداد ارقام موجود در مقدار تعیین می‌شود. برای مثال، Decimal('3.00000') حتی اگر دقت زمینه فقط ۳ باشد، هر ۵ صفر را ثبت می‌کند.

هدف از آرگومان context تعیین این است که اگر value رشته‌ای نامعتبر باشد، چه کاری انجام شود. اگر زمینه برای InvalidOperation دام داشته باشد، یک استثنا پرتاب می‌شود؛ در غیر این صورت، سازنده یک Decimal جدید با مقدار NaN برمی‌گرداند.

پس از ساخته شدن، اشیای Decimal تغییرناپذیر هستند.

تغییر یافته در نسخه‌ی 3.2: آرگومان سازنده اکنون می‌تواند یک نمونه float باشد.

تغییر یافته در نسخه‌ی 3.3: آرگومان‌های float در صورت تنظیم بودن تله‌ی FloatOperation یک استثنا پرتاب می‌کنند. به‌طور پیش‌فرض، این تله غیرفعال است.

تغییر یافته در نسخه‌ی 3.6: زیرسطرها برای گروه‌بندی مجاز هستند، همان‌گونه که در مقادیر لفظی عدد صحیح و ممیز شناور در کد استفاده می‌شوند.

اشیای ممیز شناور اعشاری بسیاری از ویژگی‌ها را با سایر انواع عددی توکار مانند float و int به اشتراک می‌گذارند. تمام عملیات ریاضی معمول و متدهای ویژه قابل اعمال هستند. به همین ترتیب، اشیای اعشاری را می‌توان کپی کرد، پیکل کرد، چاپ کرد، به‌عنوان کلیدهای دیکشنری استفاده کرد، به‌عنوان عناصر مجموعه استفاده کرد، مقایسه کرد، مرتب کرد و به نوع دیگری (مانند 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 را در عملیات حسابی با floatها یا نمونه‌هایی از fractions.Fraction ترکیب کرد: برای مثال، تلاش برای جمع کردن یک Decimal با یک float باعث پرتاب یک TypeError می‌شود. با این حال، می‌توان از عملگرهای مقایسه‌ای پایتون برای مقایسه‌ی یک نمونه‌ی Decimal یعنی x با عدد دیگری y استفاده کرد. این کار از بروز نتایج گیج‌کننده هنگام انجام مقایسه‌های برابری میان اعدادی از انواع مختلف جلوگیری می‌کند.

تغییر یافته در نسخه‌ی 3.2: مقایسه‌های بین انواع مختلف میان نمونه‌های Decimal و سایر انواع عددی اکنون به‌طور کامل پشتیبانی می‌شوند.

علاوه بر ویژگی‌های عددی استاندارد، اشیای ممیز شناور اعشاری تعدادی متد تخصصی نیز دارند:

adjusted()

توان تنظیم‌شده را پس از حذف رقم‌های سمت راست ضریب تا جایی که تنها رقم نخست باقی بماند، برمی‌گرداند: Decimal('321e+5').adjusted() عدد هفت را برمی‌گرداند. برای تعیین موقعیت باارزش‌ترین رقم نسبت به نقطه اعشار استفاده می‌شود.

as_integer_ratio()

یک جفت عدد صحیح (n, d) برمی‌گرداند که نمونه‌ی Decimal داده‌شده را به‌صورت کسر، در ساده‌ترین حالت و با مخرج مثبت نمایش می‌دهد:

>>> 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 یا b یک NaN باشد  ==> Decimal('NaN')
a < b            ==> Decimal('-1')
a == b           ==> Decimal('0')
a > b            ==> Decimal('1')
compare_signal(other, context=None)

این عملیات دقیقاً مشابه متد compare() است، با این تفاوت که همه NaNها سیگنال‌دهی می‌کنند. یعنی، اگر هیچ‌کدام از عملوندها یک NaN سیگنال‌دهنده (signaling NaN) نباشد، هر عملوند NaN ساکت (quiet NaN) به‌عنوان یک NaN سیگنال‌دهنده در نظر گرفته می‌شود.

compare_total(other, context=None)

دو عملوند را با استفاده از بازنمایی انتزاعی آن‌ها به جای مقدار عددی‌شان مقایسه می‌کند. مشابه متد compare()، اما نتیجه ترتیب کاملی بر نمونه‌های Decimal ارائه می‌دهد. دو نمونه‌ی Decimal با مقدار عددی یکسان اما بازنمایی‌های متفاوت، در این ترتیب نابرابر مقایسه می‌شوند:

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

NaNهای آرام و سیگنال‌ده (signaling) نیز در ترتیب کامل گنجانده شده‌اند. نتیجه این تابع 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 Specification است.

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') یکسان نیست. از آنجا که ۰٫۱ در نقطه‌شناور دودویی دقیقاً قابل بازنمایی نیست، مقدار به نزدیک‌ترین مقدار قابل بازنمایی ذخیره می‌شود که 0x1.999999999999ap-4 است. مقدار معادل آن در مبنای ده 0.1000000000000000055511151231257827021181583404541015625 است.

توجه

از پایتون 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 را می‌پذیرد، اما رشته‌ها یا تاپل‌ها را نمی‌پذیرد.

>>> 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)

ضرب-جمع ادغام‌شده (Fused multiply-add). حاصل 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 را برمی‌گرداند. اگر آرگومان صفر، زیرنرمال (subnormal)، بی‌نهایت یا یک NaN باشد، False را برمی‌گرداند.

is_qnan()

اگر آرگومان یک NaN ساکت (quiet 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() یک عمل منطقی است که دو عملوند منطقی می‌گیرد (به عملوندهای منطقی مراجعه کنید). نتیجه، and رقم‌به‌رقم دو عملوند است.

logical_invert(context=None)

logical_invert() یک عملیات منطقی است. نتیجه، وارونگی رقم‌به‌رقم عملوند است.

logical_or(other, context=None)

logical_or() یک عملیات منطقی است که دو عملوند منطقی می‌گیرد (ببینید عملوندهای منطقی). نتیجه، or رقم‌به‌رقم دو عملوند است.

logical_xor(other, context=None)

logical_xor() یک عملیات منطقی است که دو عملوند منطقی را می‌گیرد (ببینید عملوندهای منطقی). نتیجه، یا انحصاری رقم‌به‌رقم دو عملوند است.

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)

برای تولید مقادیر کانونیکال یک کلاس هم‌ارزی، چه در زمینه جاری و چه در زمینه مشخص‌شده، استفاده می‌شود.

این همان معنای عملیات جمع یک‌عملوندی را دارد، به‌جز اینکه اگر نتیجه نهایی متناهی باشد، به ساده‌ترین شکل خود تقلیل می‌یابد، به‌طوری‌که تمام صفرهای پایانی حذف می‌شوند و علامت آن حفظ می‌شود. یعنی تا زمانی که ضریب غیرصفر و مضربی از ده باشد، ضریب بر ده تقسیم می‌شود و توان ۱ واحد افزایش می‌یابد. در غیر این صورت (ضریب صفر است)، توان برابر ۰ قرار می‌گیرد. در همه حالت‌ها علامت بدون تغییر می‌ماند.

برای مثال، 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 سیگنال‌دهنده است.

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)

نتیجه‌ی چرخاندن ارقام اولین عملوند به میزان مشخص‌شده توسط دومین عملوند را برمی‌گرداند. دومین عملوند باید عدد صحیحی در بازه‌ی منفی دقت تا دقت باشد. مقدار مطلق دومین عملوند، تعداد موقعیت‌های چرخش را مشخص می‌کند. اگر دومین عملوند مثبت باشد، چرخش به سمت چپ است؛ در غیر این صورت، چرخش به سمت راست است. در صورت لزوم، سمت چپ ضریب اولین عملوند با صفرها پر می‌شود تا طول آن برابر با دقت شود. علامت و توان اولین عملوند بدون تغییر می‌مانند.

same_quantum(other, context=None)

بررسی می‌کند که آیا self و other توان یکسانی دارند یا اینکه هر دو NaN هستند.

این عملیات تحت تأثیر زمینه قرار نمی‌گیرد و ساکت است: هیچ پرچمی تغییر نمی‌کند و هیچ گردکردنی انجام نمی‌شود. به‌عنوان یک استثنا، نسخه‌ی C ممکن است در صورتی که عملوند دوم نتواند به‌طور دقیق تبدیل شود، استثنای InvalidOperation را پرتاب کند.

scaleb(other, context=None)

عملوند اول را با توان تنظیم‌شده توسط عملوند دوم بازمی‌گرداند. معادل آن، عملوند اول ضرب‌شده در 10**other را بازمی‌گرداند. عملوند دوم باید یک عدد صحیح باشد.

shift(other, context=None)

نتیجه‌ی جابه‌جایی ارقام عملوند اول به مقدار مشخص‌شده توسط عملوند دوم را برمی‌گرداند. عملوند دوم باید عدد صحیحی در بازه‌ی منفی دقت تا دقت باشد. قدر مطلق عملوند دوم، تعداد جایگاه‌های جابه‌جایی را مشخص می‌کند. اگر عملوند دوم مثبت باشد، جابه‌جایی به سمت چپ است؛ در غیر این صورت، جابه‌جایی به سمت راست است. ارقامی که به داخل ضریب جابه‌جا می‌شوند، صفر هستند. علامت و توان عملوند اول تغییر نمی‌کنند.

sqrt(context=None)

ریشه دوم آرگومان را با دقت کامل بازمی‌گرداند.

to_eng_string(context=None)

به یک رشته تبدیل می‌کند، و در صورت نیاز به توان، از نماد مهندسی استفاده می‌کند.

در نمادگذاری مهندسی، توان مضربی از ۳ است. این موضوع می‌تواند تا ۳ رقم را در سمت چپ نقطه اعشار باقی بگذارد و ممکن است به افزودن یک یا دو صفر انتهایی نیاز داشته باشد.

برای مثال، این 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 ارائه‌شده یا زمینه‌ی جاری استفاده می‌کند.

می‌توان اعداد اعشاری را با استفاده از تابع round() گرد کرد:

round(number)
round(number, ndigits)

اگر ndigits داده نشود یا None باشد، نزدیک‌ترین int به number بازگردانده می‌شود، به‌گونه‌ای که موارد تساوی در گرد کردن به عدد زوج گرد می‌شوند و حالت گرد کردن زمینه‌ی Decimal نادیده گرفته می‌شود. اگر number یک بی‌نهایت باشد، OverflowError پرتاب می‌شود و اگر یک NaN (ساکت یا سیگنال‌دهی) باشد، ValueError پرتاب می‌شود.

اگر ndigits یک int باشد، حالت گرد کردن زمینه رعایت می‌شود و یک Decimal برگردانده می‌شود که نشان‌دهنده‌ی number گردشده به نزدیک‌ترین مضرب Decimal('1E-ndigits') است؛ در این حالت، round(number, ndigits) معادل self.quantize(Decimal('1E-ndigits')) است. اگر number یک NaN ساکت (quiet 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'))     # context rounding ignored
4
>>> round(Decimal('3.5'))      # round-ties-to-even
4
>>> round(Decimal('3.75'), 0)  # uses the context rounding
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() انتظار دارند که آرگومان‌های آن‌ها عملوندهای منطقی باشند. یک عملوند منطقی نمونه‌ای از Decimal است که توان و علامت آن هر دو صفر هستند و تمام ارقام آن یا 0 هستند یا 1.

اشیاء زمینه

زمینه‌ها محیط‌هایی برای عملیات حسابی هستند. آن‌ها دقت را کنترل می‌کنند، قواعد گرد کردن را تنظیم می‌کنند، تعیین می‌کنند که کدام سیگنال‌ها به‌عنوان استثنا در نظر گرفته شوند، و بازه‌ی توان‌ها را محدود می‌کنند.

هر نخ زمینه‌ی جاری خود را دارد که با استفاده از توابع getcontext() و setcontext() قابل دسترسی یا تغییر است:

decimal.getcontext()

زمینه فعلی برای نخ فعال را برمی‌گرداند.

decimal.setcontext(c, /)

زمینه فعلی نخ فعال را روی c تنظیم کنید.

شما همچنین می‌توانید از دستور with و تابع localcontext() برای تغییر موقت زمینه‌ی فعال استفاده کنید.

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

یک مدیر زمینه برمی‌گرداند که هنگام ورود به دستور with، زمینه فعلی نخ فعال را به یک کپی از ctx تنظیم می‌کند و هنگام خروج از دستور with، زمینه قبلی را بازگردانی می‌کند. اگر هیچ زمینه‌ای مشخص نشده باشد، از یک کپی از زمینه فعلی استفاده می‌شود. آرگومان kwargs برای تنظیم ویژگی‌های زمینه جدید استفاده می‌شود.

برای مثال، کد زیر دقت اعشاری کنونی را روی ۴۲ رقم اعشار تنظیم می‌کند، یک محاسبه انجام می‌دهد و سپس به‌طور خودکار زمینه پیشین را بازمی‌گرداند:

from decimal import localcontext

with localcontext() as ctx:
    ctx.prec = 42   # Perform a high precision calculation
    s = calculate_something()
s = +s  # Round the final result back to the default precision

با استفاده از آرگومان‌های کلیدواژه‌ای، کد به‌شکل زیر خواهد بود:

from decimal import localcontext

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

اگر kwargs ویژگی‌ای را ارائه دهد که Context از آن پشتیبانی نمی‌کند، TypeError پرتاب می‌شود. اگر kwargs مقدار نامعتبری برای یک ویژگی ارائه دهد، یا TypeError یا ValueError پرتاب می‌شود.

تغییر یافته در نسخه‌ی 3.11: localcontext() اکنون از تنظیم ویژگی‌های زمینه از طریق آرگومان‌های کلیدواژه‌ای پشتیبانی می‌کند.

decimal.IEEEContext(bits)

یک شیء زمینه را برمی‌گرداند که با مقادیر مناسب برای یکی از قالب‌های مبادله‌ای IEEE مقداردهی اولیه‌شده است. آرگومان باید مضربی از ۳۲ و کمتر از IEEE_CONTEXT_MAX_BITS باشد.

اضافه شده در نسخه‌ی 3.14.

همچنین می‌توان زمینه‌های جدید را با استفاده از سازنده‌ی Context که در زیر توضیح داده شده است، ایجاد کرد. علاوه بر این، این ماژول سه زمینه‌ی از پیش ساخته‌شده ارائه می‌دهد:

decimal.BasicContext

این یک زمینه استاندارد است که توسط مشخصات عمومی محاسبات اعشاری (General Decimal Arithmetic Specification) تعریف شده است. دقت روی ۹ تنظیم شده است. گرد کردن روی ROUND_HALF_UP تنظیم شده است. همه پرچم‌ها پاک شده‌اند. همه تله‌ها فعال شده‌اند (به‌عنوان استثنا در نظر گرفته می‌شوند)، به جز Inexact، Rounded و Subnormal.

چون بسیاری از تله‌ها فعال هستند، این زمینه برای اشکال‌زدایی مفید است.

decimal.ExtendedContext

این یک زمینه استاندارد است که توسط مشخصات عمومی محاسبات اعشاری (General Decimal Arithmetic Specification) تعریف شده است. دقت روی ۹ تنظیم شده است. گرد کردن روی ROUND_HALF_EVEN تنظیم شده است. همه پرچم‌ها پاک شده‌اند. هیچ تله‌ای فعال نیست (تا استثناها در حین محاسبات پرتاب نشوند).

از آنجا که تله‌ها غیرفعال هستند، این زمینه برای برنامه‌هایی مفید است که ترجیح می‌دهند به‌جای پرتاب استثنا، مقدار نتیجه NaN یا Infinity باشد. این امر به برنامه اجازه می‌دهد که اجرا را در شرایطی که در غیر این صورت موجب توقف برنامه می‌شدند، به پایان برساند.

decimal.DefaultContext

این زمینه توسط سازنده‌ی Context به‌عنوان یک نمونه‌ی اولیه برای زمینه‌های جدید استفاده می‌شود. تغییر یک فیلد (مانند دقت) باعث تغییر پیش‌فرض برای زمینه‌های جدید ایجادشده توسط سازنده‌ی Context می‌شود.

این زمینه بیشترین کاربرد را در محیط‌های چندنخی دارد. تغییر یکی از فیلدها پیش از آغاز نخ‌ها، به‌منزله‌ی تنظیم پیش‌فرض‌های سراسری سیستم است. تغییر فیلدها پس از آغاز نخ‌ها توصیه نمی‌شود، زیرا نیازمند همگام‌سازی نخ‌ها برای جلوگیری از شرایط رقابتی خواهد بود.

در محیط‌های تک‌نخی، بهتر است اصلاً از این زمینه استفاده نکنید. در عوض، به‌سادگی زمینه‌ها را به‌صراحت همان‌طور که در زیر توضیح داده شده است ایجاد کنید.

مقادیر پیش‌فرض عبارت‌اند از Context.prec=28، Context.rounding=ROUND_HALF_EVEN، و تله‌های فعال برای Overflow، InvalidOperation و DivisionByZero.

علاوه بر سه زمینه‌ی فراهم‌شده، می‌توان زمینه‌های جدید را با سازنده‌ی Context ایجاد کرد.

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

یک زمینه جدید ایجاد می‌کند. اگر فیلدی مشخص‌نشده باشد یا None باشد، مقادیر پیش‌فرض از DefaultContext کپی می‌شوند. اگر فیلد flags مشخص‌نشده باشد یا None باشد، تمام پرچم‌ها پاک می‌شوند.

prec

یک عدد صحیح در بازه‌ی [1, MAX_PREC] که دقت عملیات حسابی را در زمینه تنظیم می‌کند.

rounding

یکی از ثابت‌های فهرست‌شده در بخش Rounding Modes.

traps
flags

فهرست‌هایی از هر سیگنالی که باید تنظیم شود. به‌طور کلی، زمینه‌های جدید فقط باید تله‌ها را تنظیم کنند و پرچم‌ها را پاک باقی بگذارند.

Emin
Emax

اعداد صحیحی که کران‌های بیرونی مجاز برای توان‌ها را مشخص می‌کنند. Emin باید در بازه‌ی [MIN_EMIN، 0] باشد، Emax در بازه‌ی [0، MAX_EMAX].

capitals

یا 0 یا 1 (پیش‌فرض). اگر روی 1 تنظیم شود، توان‌ها با E بزرگ چاپ می‌شوند؛ در غیر این صورت، از e کوچک استفاده می‌شود: Decimal('6.02e+23').

clamp

یا 0 (پیش‌فرض) یا 1. اگر روی 1 تنظیم شود، توان e نمونه‌ی Decimal قابل‌نمایش در این زمینه، به‌طور دقیق به محدوده 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 چندین متد با کاربرد عمومی و همچنین تعداد زیادی متد برای انجام عملیات حسابی به‌صورت مستقیم در یک زمینه‌ی داده‌شده تعریف می‌کند. علاوه بر این، به ازای هر یک از متدهای Decimal که در بالا توضیح داده شده‌اند (به‌استثنای متدهای adjusted() و as_tuple())، یک متد متناظر در Context وجود دارد. برای مثال، برای یک نمونه‌ی Context به نام C و یک نمونه‌ی Decimal به نام x، عبارت C.exp(x) معادل x.exp(context=C) است. هر متد Context در هر جا که یک نمونه‌ی Decimal پذیرفته شود، یک عدد صحیح پایتون (نمونه‌ای از int) را می‌پذیرد.

clear_flags()

همه‌ی پرچم‌ها را به 0 بازنشانی می‌کند.

clear_traps()

همه‌ی تله‌ها را به 0 بازنشانی می‌کند.

اضافه شده در نسخه‌ی 3.3.

copy()

یک کپی از زمینه را برمی‌گرداند.

copy_decimal(num, /)

یک رونوشت از نمونه‌ی Decimal به نام num برمی‌گرداند.

create_decimal(num='0', /)

یک نمونه جدید از Decimal را از num ایجاد می‌کند، اما از self به‌عنوان زمینه استفاده می‌کند. برخلاف سازنده‌ی Decimal، دقت زمینه، روش گرد کردن، پرچم‌ها و تله‌ها در تبدیل اعمال می‌شوند.

این مفید است، زیرا ثابت‌ها اغلب با دقتی بیشتر از حد نیاز برنامه ارائه می‌شوند. مزیت دیگر این است که گرد کردن بلافاصله اثرات ناخواسته‌ی ارقام فراتر از دقت فعلی را حذف می‌کند. در مثال زیر، استفاده از ورودی‌های گردنشده به این معناست که افزودن صفر به یک مجموع می‌تواند نتیجه را تغییر دهد:

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

این متد عملیات تبدیل به عددِ مشخصات IBM را پیاده‌سازی می‌کند. اگر آرگومان یک رشته باشد، هیچ‌گونه فضای سفید یا زیرخطی در ابتدا یا انتها مجاز نیست.

create_decimal_from_float(f, /)

یک نمونه جدید Decimal از float f ایجاد می‌کند، اما گرد کردن با استفاده از self به‌عنوان زمینه انجام می‌شود. برخلاف متد کلاس Decimal.from_float()، دقت زمینه، روش گرد کردن، پرچم‌ها و تله‌ها بر تبدیل اعمال می‌شوند.

>>> 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 برمی‌گرداند که کمترین مقدار توان برای نتایج زیرنرمال است. هنگامی که زیرریز (underflow) رخ می‌دهد، توان روی Etiny تنظیم می‌شود.

Etop()

مقداری برابر با Emax - prec + 1 برمی‌گرداند.

رویکرد معمول برای کار با اعداد اعشاری، ایجاد نمونه‌های Decimal و سپس اعمال عملیات حسابی است که در زمینه‌ی جاری برای نخ فعال انجام می‌شوند. رویکرد جایگزین، استفاده از متدهای زمینه برای محاسبه در یک زمینه‌ی مشخص است. این متدها مشابه متدهای کلاس 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 برمی‌گرداند که علامت آن روی ۰ تنظیم شده است.

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 یک عدد عادی باشد، True را برمی‌گرداند؛ در غیر این صورت False را برمی‌گرداند.

is_qnan(x, /)

اگر x یک NaN ساکت (quiet NaN) باشد، True را برمی‌گرداند؛ در غیر این صورت False را برمی‌گرداند.

is_signed(x, /)

اگر x منفی باشد، True را برمی‌گرداند؛ در غیر این صورت False را برمی‌گرداند.

is_snan(x, /)

اگر x یک NaN سیگنال‌دهنده باشد، True را برمی‌گرداند؛ در غیر این صورت False را برمی‌گرداند.

is_subnormal(x, /)

اگر x زیرنرمال باشد، True را برمی‌گرداند؛ در غیر این صورت False را برمی‌گرداند.

is_zero(x, /)

اگر x صفر باشد، True را برمی‌گرداند؛ در غیر این صورت False را برمی‌گرداند.

ln(x, /)

لگاریتم طبیعی x (مبنای e) را برمی‌گرداند.

log10(x, /)

لگاریتم x در مبنای ۱۰ را برمی‌گرداند.

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, /)

منها با عملگر پیشوندی یک‌عملوندی منها در پایتون متناظر است.

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 معادل عملگر یک‌عملوندی پیش‌وندی پلاس در پایتون است. این عملیات دقت و گرد کردن زمینه را اعمال می‌کند، بنابراین یک عملیات همانی نیست.

power(x, y, modulo=None)

x به توان y را برمی‌گرداند و در صورت داده شدن، به پیمانه‌ی modulo کاهش می‌یابد.

با دو آرگومان، x**y محاسبه می‌شود. اگر x منفی باشد، y باید عدد صحیح باشد. نتیجه نادقیق خواهد بود، مگر اینکه y عدد صحیح باشد و نتیجه متناهی باشد و بتوان آن را دقیقاً با 'precision' رقم بیان کرد. از حالت گرد کردن زمینه استفاده می‌شود. نتایج در نسخه‌ی پایتون همیشه به‌درستی گرد می‌شوند.

Decimal(0) ** Decimal(0) منجر به InvalidOperation می‌شود، و اگر InvalidOperation به دام نیفتد، نتیجه Decimal('NaN') خواهد بود.

تغییر یافته در نسخه‌ی 3.3: ماژول C، power() را بر حسب توابع exp() و ln() که به‌درستی گرد شده‌اند محاسبه می‌کند. نتیجه خوش‌تعریف است، اما فقط «تقریباً همیشه به‌درستی گرد شده» است.

با سه آرگومان، (x**y) % modulo را محاسبه می‌کند. برای قالب با سه آرگومان، محدودیت‌های زیر روی آرگومان‌ها برقرار است:

  • هر سه آرگومان باید عدد صحیح باشند

  • y باید غیرمنفی باشد

  • حداقل یکی از x یا y باید غیرصفر باشد

  • modulo باید غیرصفر باشد و حداکثر 'precision' رقم داشته باشد

مقدار حاصل از Context.power(x, y, modulo) برابر با مقداری است که از محاسبه‌ی (x**y) % modulo با دقت نامحدود به دست می‌آید، اما به‌صورت کارآمدتری محاسبه می‌شود. توان نتیجه صفر است، صرف‌نظر از توان‌های x، y و modulo. نتیجه همیشه دقیق است.

quantize(x, y, /)

مقداری برابر با x (گردشده) برمی‌گرداند که دارای توان y است.

radix()

فقط ۱۰ را برمی‌گرداند، زیرا این Decimal است، :)

remainder(x, y, /)

باقی‌مانده‌ی تقسیم عدد صحیح را برمی‌گرداند.

علامت نتیجه، اگر غیرصفر باشد، همان علامت مقسوم اصلی است.

remainder_near(x, y, /)

x - y * n را برمی‌گرداند، که در آن n نزدیک‌ترین عدد صحیح به مقدار دقیق x / y است (اگر نتیجه ۰ باشد، علامت آن علامت x خواهد بود).

rotate(x, y, /)

نسخه‌ای چرخش‌یافته از x را به تعداد y بار برمی‌گرداند.

same_quantum(x, y, /)

اگر دو عملوند توان یکسانی داشته باشند، True برمی‌گرداند.

scaleb(x, y, /)

اولین عملوند را پس از افزودن مقدار دوم به توان آن برمی‌گرداند.

shift(x, y, /)

رونوشتی از x برمی‌گرداند که y بار جابه‌جاشده است.

sqrt(x, /)

ریشه دوم یک عدد غیرمنفی تا دقت زمینه.

subtract(x, y, /)

اختلاف بین x و y را برمی‌گرداند.

to_eng_string(x, /)

به یک رشته تبدیل می‌کند، و در صورت نیاز به توان، از نماد مهندسی استفاده می‌کند.

در نمادگذاری مهندسی، توان مضربی از ۳ است. این موضوع می‌تواند تا ۳ رقم را در سمت چپ نقطه اعشار باقی بگذارد و ممکن است به افزودن یک یا دو صفر انتهایی نیاز داشته باشد.

to_integral_exact(x, /)

به یک عدد صحیح گرد می‌شود.

to_sci_string(x, /)

یک عدد را با استفاده از نماد علمی به رشته تبدیل می‌کند.

ثابت‌ها

ثابت‌های این بخش تنها برای ماژول C مرتبط هستند. این ثابت‌ها برای سازگاری در نسخه پایتون خالص نیز گنجانده شده‌اند.

۳۲ بیتی

۶۴ بیتی

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 است. منسوخ شده است، زیرا پایتون اکنون همیشه نخ دارد.

منسوخ شده از نسخه‌ی 3.9.

decimal.HAVE_CONTEXTVAR

مقدار پیش‌فرض True است. اگر پایتون با گزینه‌ی --without-decimal-contextvar پیکربندی شده باشد، نسخه‌ی C به‌جای زمینه‌ی محلی به هم‌روال از زمینه‌ی محلی به نخ استفاده می‌کند و مقدار False خواهد بود. این حالت در برخی سناریوهای زمینه‌ی تودرتو کمی سریع‌تر است.

اضافه شده در نسخه‌ی 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

اگر آخرین رقم پس از گرد کردن به سمت صفر، ۰ یا ۵ باشد، به دور از صفر گرد می‌شود؛ در غیر این صورت به سمت صفر گرد می‌شود.

سیگنال‌ها

سیگنال‌ها نشان‌دهنده‌ی شرایطی هستند که در حین محاسبه رخ می‌دهند. هر یک با یک پرچم زمینه و یک فعال‌ساز تله‌ی زمینه متناظر است.

پرچم زمینه هرگاه که شرط رخ دهد تنظیم می‌شود. پس از محاسبه، پرچم‌ها را می‌توان برای اهداف اطلاع‌رسانی بررسی کرد (برای نمونه، برای تعیین اینکه آیا یک محاسبه دقیق بوده است). پس از بررسی پرچم‌ها، حتماً همه‌ی پرچم‌ها را پیش از آغاز محاسبه‌ی بعدی پاک کنید.

اگر فعال‌ساز تله‌ی زمینه برای سیگنال تنظیم شده باشد، آنگاه شرط باعث پرتاب یک استثنای پایتون می‌شود. برای مثال، اگر تله‌ی DivisionByZero تنظیم شده باشد، هنگام مواجهه با شرط، یک استثنای DivisionByZero پرتاب می‌شود.

class decimal.Clamped

توانی برای تطابق با محدودیت‌های بازنمایی تغییر داده شد.

معمولاً، محدودسازی (clamping) زمانی رخ می‌دهد که یک توان خارج از محدوده‌های Emin و Emax زمینه قرار گیرد. در صورت امکان، توان با افزودن صفر به ضریب کاهش می‌یابد تا در محدوده قرار گیرد.

class decimal.DecimalException

کلاس پایه برای سایر سیگنال‌ها و زیرکلاسی از ArithmeticError.

class decimal.DivisionByZero

نشان‌دهنده تقسیم یک عدد غیربی‌نهایت بر صفر است.

ممکن است در تقسیم، تقسیم پیمانه‌ای، یا هنگام رساندن یک عدد به توان منفی رخ دهد. اگر این سیگنال به دام نیفتد، Infinity یا -Infinity را با علامتی که توسط ورودی‌های محاسبه تعیین می‌شود برمی‌گرداند.

class decimal.Inexact

نشان می‌دهد که گرد کردن رخ داده است و نتیجه دقیق نیست.

سیگنال زمانی رخ می‌دهد که رقم‌های غیرصفر در حین گرد کردن دور ریخته شوند. نتیجه‌ی گرد شده بازگردانده می‌شود. پرچم سیگنال یا تله برای تشخیص زمانی که نتایج نادقیق هستند استفاده می‌شود.

class decimal.InvalidOperation

یک عملیات نامعتبر انجام شد.

نشان می‌دهد که عملیاتی درخواست شده است که معنادار نیست. اگر تله‌گذاری (trap) نشده باشد، 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

فعال‌سازی معناشناسی سخت‌گیرانه‌تر برای ترکیب اعداد اعشاری و Decimalها.

اگر سیگنال به دام نیفتد (پیش‌فرض)، ترکیب شناورها و Decimalها در سازنده‌ی Decimal، create_decimal() و تمام عملگرهای مقایسه‌ای مجاز است. هم تبدیل‌ها و هم مقایسه‌ها دقیق هستند. هر بار وقوع یک عملیات مختلط، به‌صورت خاموش با تنظیم 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 را ممکن می‌سازد)؛ با این حال، برخی عملیات هنوز ممکن است دچار خطای گرد کردن شوند، هنگامی که ارقام غیرصفر از دقت ثابت بیشتر شوند.

اثرات خطای گرد کردن می‌تواند با جمع یا تفریق کمیت‌هایی که تقریباً یکدیگر را خنثی می‌کنند، تشدید شود و به از دست رفتن ارقام معنادار بینجامد. کنوت دو مثال آموزنده ارائه می‌دهد که در آن‌ها حساب ممیز شناور گردشده با دقت ناکافی باعث از کار افتادن ویژگی‌های شرکت‌پذیری و توزیع‌پذیری جمع می‌شود:

# Examples from Seminumerical Algorithms, Section 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 به دام نیفتاده باشد، بی‌نهایت می‌تواند در اثر گرد کردن فراتر از محدوده‌ی بزرگ‌ترین عدد قابل نمایش حاصل شود.

بی‌نهایت‌ها علامت‌دار (affine) هستند و می‌توان از آن‌ها در عملیات حسابی استفاده کرد، که در آن‌ها به‌عنوان اعدادی بسیار بزرگ و نامعین در نظر گرفته می‌شوند. برای مثال، افزودن یک ثابت به بی‌نهایت، نتیجه‌ی بی‌نهایت دیگری می‌دهد.

برخی عملیات‌ها نامعین هستند و NaN را برمی‌گردانند، یا اگر سیگنال InvalidOperation به دام افتاده باشد، استثنایی را پرتاب می‌کنند. برای مثال، 0/0 مقدار NaN را برمی‌گرداند که به معنای «عدد نیست» است. این نوع NaN ساکت است و پس از ایجاد، در دیگر محاسبات جریان می‌یابد و همیشه به NaN دیگری منجر می‌شود. این رفتار می‌تواند برای مجموعه‌ای از محاسبات که گاهی ورودی‌های ناموجود دارند مفید باشد — این امر اجازه می‌دهد محاسبه ادامه یابد، در حالی که نتایج خاصی را به‌عنوان نامعتبر علامت‌گذاری می‌کند.

یکی از گونه‌ها sNaN است که به‌جای ساکت ماندن پس از هر عملیات، سیگنال می‌دهد. این مقدار بازگشتی مفیدی است، هنگامی که نیاز است یک نتیجه نامعتبر محاسبه‌ای را برای مدیریت ویژه متوقف کند.

رفتار عملگرهای مقایسه‌ای پایتون می‌تواند در مواردی که یک NaN در میان باشد، کمی غافلگیرکننده باشد. آزمون برابری در صورتی که یکی از عملوندها یک NaN ساکت یا سیگنال‌دهنده باشد، همیشه False برمی‌گرداند (حتی هنگام انجام Decimal('NaN')==Decimal('NaN'))، در حالی که آزمون نابرابری همیشه True برمی‌گرداند. تلاش برای مقایسه‌ی دو Decimal با استفاده از هر یک از عملگرهای <، <=، > یا >=، در صورتی که یکی از عملوندها NaN باشد، سیگنال InvalidOperation را پرتاب می‌کند و اگر این سیگنال به دام نیفتد، False برمی‌گرداند. توجه داشته باشید که مشخصه‌ی General Decimal Arithmetic رفتار مقایسه‌های مستقیم را تعیین نمی‌کند؛ این قواعد برای مقایسه‌های شامل یک NaN از استاندارد IEEE 854 گرفته شده‌اند (جدول ۳ در بخش ۵.۷ را ببینید). برای اطمینان از انطباق دقیق با استانداردها، در عوض از متدهای compare() و compare_signal() استفاده کنید.

صفرهای علامت‌دار می‌توانند از محاسباتی که دچار زیرریز (underflow) می‌شوند حاصل شوند. آن‌ها علامتی را حفظ می‌کنند که اگر محاسبه با دقت بیشتری انجام می‌شد، حاصل می‌شد. از آنجا که بزرگی آن‌ها صفر است، صفرهای مثبت و منفی هر دو برابر در نظر گرفته می‌شوند و علامت آن‌ها صرفاً اطلاع‌رسانی است.

علاوه بر دو صفر علامت‌دار که متمایز اما برابر هستند، نمایش‌های گوناگونی از صفر با دقت‌های متفاوت اما هم‌ارز در مقدار وجود دارد. این موضوع کمی نیاز به عادت کردن دارد. برای چشمی که به نمایش‌های نقطه‌شناور نرمال‌شده عادت کرده است، فوراً بدیهی نیست که محاسبه‌ی زیر مقداری برابر با صفر برمی‌گرداند:

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

کار با نخ‌ها

تابع getcontext() برای هر نخ به یک شیء Context متفاوت دسترسی دارد. داشتن زمینه‌های جداگانه برای نخ‌ها به این معناست که نخ‌ها می‌توانند تغییراتی (مانند getcontext().prec=10) بدون تداخل با سایر نخ‌ها ایجاد کنند.

به همین ترتیب، تابع setcontext() به‌طور خودکار هدف خود را به نخ جاری اختصاص می‌دهد.

اگر setcontext() پیش از getcontext() فراخوانی نشده باشد، آنگاه getcontext() به‌طور خودکار یک زمینه جدید برای استفاده در نخ جاری ایجاد می‌کند. اشیای زمینه جدید دارای مقادیر پیش‌فرضی هستند که از شیء decimal.DefaultContext تنظیم شده‌اند.

پرچم sys.flags.thread_inherit_context بر زمینه‌ی نخ‌های جدید تأثیر می‌گذارد. اگر پرچم نادرست باشد، نخ‌های جدید با یک زمینه‌ی خالی آغاز می‌شوند. در این حالت، getcontext() هنگام فراخوانی یک شیء زمینه‌ی جدید ایجاد می‌کند و از مقادیر پیش‌فرض DefaultContext استفاده می‌کند. اگر پرچم درست باشد، نخ‌های جدید با رونوشتی از زمینه‌ی فراخواننده‌ی threading.Thread.start() آغاز می‌شوند.

برای کنترل پیش‌فرض‌ها به گونه‌ای که هر نخ در سراسر برنامه از مقادیر یکسانی استفاده کند، مستقیماً شیء DefaultContext را تغییر دهید. این کار باید پیش از شروع هر نخی انجام شود تا شرایط رقابتی بین نخ‌هایی که getcontext() را فراخوانی می‌کنند، وجود نداشته باشد. برای مثال:

# Set applicationwide defaults for all threads about to be launched
DefaultContext.prec = 12
DefaultContext.rounding = ROUND_DOWN
DefaultContext.traps = ExtendedContext.traps.copy()
DefaultContext.traps[InvalidOperation] = 1
setcontext(DefaultContext)

# Afterwards, the threads can be started
t1.start()
t2.start()
t3.start()
 . . .

دستورهای عملی

در ادامه چند راه‌حل آورده شده است که به‌عنوان توابع سودمند به کار می‌روند و روش‌هایی برای کار با کلاس Decimal را نشان می‌دهند:

def moneyfmt(value, places=2, curr='', sep=',', dp='.',
             pos='', neg='-', trailneg=''):
    """Convert Decimal to a money formatted string.

    places:  required number of places after the decimal point
    curr:    optional currency symbol before the sign (may be blank)
    sep:     optional grouping separator (comma, period, space, or blank)
    dp:      decimal point indicator (comma or period)
             only specify as blank when places is zero
    pos:     optional sign for positive numbers: '+', space or blank
    neg:     optional sign for negative numbers: '-', '(', space or blank
    trailneg:optional trailing minus indicator:  '-', ')', space or blank

    >>> 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 places --> '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():
    """Compute Pi to the current precision.

    >>> print(pi())
    3.141592653589793238462643383

    """
    getcontext().prec += 2  # extra digits for intermediate steps
    three = Decimal(3)      # substitute "three=3.0" for regular floats
    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               # unary plus applies the new precision

def exp(x):
    """Return e raised to the power of x.  Result type matches input type.

    >>> 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):
    """Return the cosine of x as measured in radians.

    The Taylor series approximation works best for a small value of x.
    For larger values, first compute 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):
    """Return the sine of x as measured in radians.

    The Taylor series approximation works best for a small value of x.
    For larger values, first compute 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')

پرسش: در یک برنامه ممیز ثابت با دو رقم اعشار، برخی ورودی‌ها رقم‌های اعشار زیادی دارند و باید گرد شوند. برخی دیگر نباید ارقام اضافی داشته باشند و باید اعتبارسنجی شوند. از چه متدهایی باید استفاده کرد؟

A: متد 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 این است که اعداد دقیق فرض می‌شوند و مستقل از زمینه‌ی جاری ایجاد می‌شوند. حتی می‌توانند دقتی بیشتر از زمینه‌ی جاری داشته باشند. محاسبات با آن ورودی‌های دقیق انجام می‌شوند و سپس گرد کردن (یا سایر عملیات زمینه) به نتیجه‌ی محاسبه اعمال می‌شود:

>>> getcontext().prec = 5
>>> pi = Decimal('3.1415926535')   # More than 5 digits
>>> pi                             # All digits are retained
Decimal('3.1415926535')
>>> pi + 0                         # Rounded after an addition
Decimal('3.1416')
>>> pi - Decimal('0.00005')        # Subtract unrounded numbers, then round
Decimal('3.1415')
>>> pi + 0 - Decimal('0.00005').   # Intermediate values are rounded
Decimal('3.1416')

پرسش: برخی مقادیر اعشاری همیشه با نماد نمایی چاپ می‌شوند. آیا راهی برای دریافت نمایش غیرنمایی وجود دارد؟

پاسخ: برای برخی از مقدارها، نماد نمایی تنها راه بیان تعداد ارقام معنادار در ضریب است. برای مثال، بیان 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')

پرسش: آیا راهی برای تبدیل یک عدد اعشاری معمولی به Decimal وجود دارد؟

پ: بله، هر عدد ممیز شناور دودویی را می‌توان دقیقاً به‌صورت یک Decimal بیان کرد، هرچند یک تبدیل دقیق ممکن است به دقت بیشتری نسبت به آنچه به‌طور شهودی انتظار می‌رود نیاز داشته باشد:

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

پرسش: در یک محاسبه‌ی پیچیده، چگونه می‌توانم مطمئن شوم که به دلیل دقت ناکافی یا ناهنجاری‌های گردکردن، نتیجه‌ای کاذب به دست نیاورده‌ام.

پاسخ: ماژول decimal آزمایش نتایج را آسان می‌کند. بهترین روش این است که محاسبات را با دقت بیشتر و با حالت‌های مختلف گرد کردن دوباره اجرا کنید. نتایج بسیار متفاوت، دقت ناکافی، مشکلات مربوط به حالت گرد کردن، ورودی‌های بدشرط یا یک الگوریتم ناپایدار عددی را نشان می‌دهند.

پرسش: متوجه شده‌ام که دقت زمینه بر نتایج عملیات اعمال می‌شود، اما نه بر ورودی‌ها. آیا هنگام ترکیب مقادیر با دقت‌های مختلف، نکته‌ای وجود دارد که باید به آن توجه کنید؟

پاسخ: بله. اصل این است که همه مقادیر دقیق در نظر گرفته می‌شوند و عملیات حسابی روی آن مقادیر نیز دقیق است. فقط نتایج گرد می‌شوند. مزیت آن برای ورودی‌ها این است که «آنچه تایپ می‌کنید، همان را دریافت می‌کنید». عیب آن این است که اگر فراموش کنید ورودی‌ها گرد نشده‌اند، نتایج ممکن است عجیب به نظر برسند:

>>> 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')      # unary plus triggers rounding
Decimal('1.23')

به‌عنوان جایگزین، ورودی‌ها می‌توانند در زمان ایجاد با استفاده از متد Context.create_decimal() گرد شوند:

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

پرسش: آیا پیاده‌سازی CPython برای اعداد بزرگ سریع است؟

پاسخ: بله. در پیاده‌سازی‌های CPython و PyPy3، نسخه‌های C/CFFI ماژول decimal از کتابخانه پرسرعت libmpdec برای حساب ممیز شناور اعشاری با دقت دلخواه و گردکردن صحیح بهره می‌برند [1]. libmpdec برای اعداد با اندازه متوسط از ضرب کاراتسوبا و برای اعداد بسیار بزرگ از تبدیل نظریه‌ای اعداد (Number Theoretic Transform) استفاده می‌کند.

زمینه باید برای عملیات حسابی دقیق با دقت دلخواه تطبیق داده شود. Emin و Emax باید همیشه روی مقادیر بیشینه تنظیم شوند، clamp باید همیشه ۰ (پیش‌فرض) باشد. تنظیم prec به کمی دقت نیاز دارد.

ساده‌ترین روش برای آزمایش حساب اعداد بزرگ (bignum arithmetic) این است که از حداکثر مقدار prec نیز استفاده کنید [2]:

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

برای نتایج غیردقیق، MAX_PREC در پلتفرم‌های ۶۴ بیتی بسیار بیش‌ازحد بزرگ است و حافظه‌ی در دسترس کافی نخواهد بود:

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

در سیستم‌هایی با تخصیص بیش‌ازحد (overallocation)، مانند لینوکس، رویکرد پیشرفته‌تر این است که prec را متناسب با مقدار RAM در دسترس تنظیم کنید. فرض کنید ۸ گیگابایت RAM دارید و انتظار ۱۰ عملوند همزمان را دارید که هرکدام حداکثر ۵۰۰ مگابایت مصرف می‌کنند:

>>> import sys
>>>
>>> # Maximum number of digits for a single operand using 500MB in 8-byte words
>>> # with 19 digits per word (4-byte and 9 digits for the 32-bit build):
>>> maxdigits = 19 * ((500 * 1024**2) // 8)
>>>
>>> # Check that this works:
>>> c = Context(prec=maxdigits, Emax=MAX_EMAX, Emin=MIN_EMIN)
>>> c.traps[Inexact] = True
>>> setcontext(c)
>>>
>>> # Fill the available precision with nines:
>>> 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'>]

به‌طور کلی (و به‌ویژه در سیستم‌های بدون تخصیص بیش‌ازحد (overallocation))، توصیه می‌شود کران‌های حتی محدودتری را برآورد کنید و اگر انتظار می‌رود همه‌ی محاسبات دقیق باشند، تله‌ی Inexact را تنظیم کنید.