الفرق بين المراجعتين لصفحة: «Python/decimal»

من موسوعة حسوب
أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE:الأعداد العشرية decimal في بايثون}}</noinclude> تتيح وحدة <code>decimal</code> إجراء حسابات سريع...'
 
لا ملخص تعديل
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:الأعداد العشرية decimal في بايثون}}</noinclude>
<noinclude>{{DISPLAYTITLE:الأعداد العشرية decimal في بايثون}}</noinclude>


تتيح وحدة <code>decimal</code> إجراء حسابات سريعة على الأعداد العشرية مع ضمان التقريب الصحيح.<syntaxhighlight lang="python3">
تتيح [[الوحدات في بايثون|وحدة]] <code>decimal</code> إجراء حسابات سريعة على الأعداد العشرية مع ضمان التقريب الصحيح.<syntaxhighlight lang="python3">
>>> import decimal
>>> import decimal


سطر 16: سطر 16:
Decimal('3.140000000000000124344978758017532527446746826171875')
Decimal('3.140000000000000124344978758017532527446746826171875')


</syntaxhighlight>تتفوق هذه الوحدة على نوع الأعداد العشرية float بعدة ميزات:
</syntaxhighlight>تتفوق هذه [[الوحدات في بايثون|الوحدة]] على نوع الأعداد العشرية float بعدة ميزات:
* العدد العشري decimal "يستند إلى نموذج أعداد عشرية ذات فاصلة عائمة يراعي الاستخدام البشري ويلتزم بمبدأ أساسي هو أنّه يجب أن توفّر الحواسيب عمليات حسابية تعمل بنفس الطريقة التي يتعلّمها الناس في المدارس" - حسب مواصفات العمليات الحسابية التي تجرى على الأعداد العشرية decimal.
* العدد العشري decimal "يستند إلى نموذج أعداد عشرية ذات فاصلة عائمة يراعي الاستخدام البشري ويلتزم بمبدأ أساسي هو أنّه يجب أن توفّر الحواسيب عمليات حسابية تعمل بنفس الطريقة التي يتعلّمها الناس في المدارس" - حسب مواصفات العمليات الحسابية التي تجرى على الأعداد العشرية decimal.


* يمكن تمثيل الأعداد العشرية decimal بدقّة، أما الأرقام مثل <code>1.1</code> و <code>2.2</code> فلا تمثل تمثيلًا دقيقًا في النظام الثنائي للأعداد ذات الفاصلة العائمة. ولا يتوقع المستخدم أن تعطي العملية الحسابية ‎<code>1.1 + 2.2‎</code> النتيجة <code>3.3000000000000003</code> كما هو الحال مع الأعداد في النظام الثنائي للأعداد ذات الفاصلة العائمة.
* يمكن تمثيل الأعداد العشرية decimal بدقّة، أما الأرقام مثل <code>1.1</code> و <code>2.2</code> فلا تمثل تمثيلًا دقيقًا في النظام الثنائي [[الأعداد العشرية (ذات الفاصلة العائمة) float في بايثون|للأعداد ذات الفاصلة العائمة]]. ولا يتوقع المستخدم أن تعطي العملية الحسابية ‎<code>1.1 + 2.2‎</code> النتيجة <code>3.3000000000000003</code> كما هو الحال مع الأعداد في النظام الثنائي للأعداد ذات الفاصلة العائمة.


* تحافظ الأعداد العشرية decimal على الدقة عند إجراء العمليات الحسابية، ففي هذا النظام يكون ناتج العمليات التالية: <code>‎0.1 + 0.1 + 0.1 - 0.3</code> هو الصفر، أما في النظام الثنائي للفاصلة العائمة يكون الناتج <code>5.5511151231257827e-017</code>. صحيح أن هذا الرقم قريب جدًّا من الصفر، ولكن تعيق هذه الفروقات إجراء عمليات مقارنة دقيقة للمساواة إلى جانب أنّ هذه الفروقات يمكن أن تتزايد مع الاستمرار في إجراء العمليات الحسابية؛ لذا يفضل استخدام النوع decimal في التطبيقات المحاسبية التي تتطلّب إجراء مقارنات مساواة صارمة.
* تحافظ الأعداد العشرية decimal على الدقة عند إجراء العمليات الحسابية، ففي هذا النظام يكون ناتج العمليات التالية: <code>‎0.1 + 0.1 + 0.1 - 0.3</code> هو الصفر، أما في النظام الثنائي للفاصلة العائمة يكون الناتج <code>5.5511151231257827e-017</code>. صحيح أن هذا الرقم قريب جدًّا من الصفر، ولكن تعيق هذه الفروقات إجراء عمليات مقارنة دقيقة للمساواة إلى جانب أنّ هذه الفروقات يمكن أن تتزايد مع الاستمرار في إجراء العمليات الحسابية؛ لذا يفضل استخدام النوع decimal في التطبيقات المحاسبية التي تتطلّب إجراء مقارنات مساواة صارمة.


* تعتمد وحدة decimal مفهوم الأعداد الاعتبارية significant؛ لذا فإنّ ناتج العملية ‎<code>1.30 + 1.20</code> هو <code>2.50</code>، حيث تحتفظ اللغة بالصفر الأخير إشارة إلى أنّه عدد اعتباري. مفهوم الأعداد الاعتبارية هو من المفاهيم الشائعة لتمثيل الأرقام في التطبيقات المالية والمحاسبية. وفي عملية الضرب تستخدم جميع الأرقام للحصول على الناتج، فعلى سبيل المثال تعطي العملية <code>‎1.3 * 1.2</code> الناتج <code>1.56</code> أما العملية <code>‎1.30 * 1.20</code> فتعطي الناتج <code>1.5600</code>.
* تعتمد [[الوحدات في بايثون|وحدة]] decimal مفهوم الأعداد المعنوية significant؛ لذا فإنّ ناتج العملية ‎<code>1.30 + 1.20</code> هو <code>2.50</code>، حيث تحتفظ اللغة بالصفر الأخير إشارة إلى أنّه عدد معنوي. مفهوم الأعداد المعنوية هو من المفاهيم الشائعة لتمثيل الأرقام في التطبيقات المالية والمحاسبية. وفي عملية الضرب تستخدم جميع الأرقام للحصول على الناتج، فعلى سبيل المثال تعطي العملية <code>‎1.3 * 1.2</code> الناتج <code>1.56</code> أما العملية <code>‎1.30 * 1.20</code> فتعطي الناتج <code>1.5600</code>.


* على عكس الأرقام العشرية ذات الفاصلة العائمة، يمكن تحديد مقدار الدقة المعتمدة في الأعداد العشرية decimal من قبل المستخدم (القيمة الافتراضية هي 28 مرتبة) ويمكن استخدام أي عدد مهما كان كبيرًا، مثال:
* على عكس [[الأعداد العشرية (ذات الفاصلة العائمة) float في بايثون|الأعداد العشرية ذات الفاصلة العائمة]]، يمكن تحديد مقدار الدقة المعتمدة في الأعداد العشرية decimal من قبل المستخدم (القيمة الافتراضية هي 28 مرتبة) ويمكن استخدام أي عدد مهما كان كبيرًا، مثال:
<syntaxhighlight lang="python3">
<syntaxhighlight lang="python3">
>>> from decimal import *
>>> from decimal import *
سطر 41: سطر 41:
Decimal('0.1428571428571428571428571429')
Decimal('0.1428571428571428571428571429')
</syntaxhighlight>
</syntaxhighlight>
* تستخدم الأعداد العشرية بنوعيها float و decimal في بايثون بالاعتماد على المعايير المعروفة، ويعرض النوع float جزءًا بسيطًا من هذه المعايير، في حين أنّ وحدة decimal تعرض جميع الأجزاء المطلوبة ضمن هذه المعايير. ويمكن للمبرمج - عند الحاجة - أن يسيطر بصورة تامة على عمليات التقريب والتعامل مع الإشارات signals، ويمكن كذلك فرض عمليات حسابية دقيقة ومضبوطة باستخدام استثناءات توقف تنفيذ أي عملية حسابية غير دقيقة.
* تستخدم الأعداد العشرية بنوعيها float و decimal في بايثون بالاعتماد على المعايير المعروفة، ويعرض النوع float جزءًا بسيطًا من هذه المعايير، في حين أنّ [[الوحدات في بايثون|وحدة]] decimal تعرض جميع الأجزاء المطلوبة ضمن هذه المعايير. ويمكن للمبرمج - عند الحاجة - أن يسيطر بصورة تامة على عمليات التقريب والتعامل مع الإشارات signals، ويمكن كذلك فرض عمليات حسابية دقيقة ومضبوطة باستخدام استثناءات توقف تنفيذ أي عملية حسابية غير دقيقة.


* صمّمت وحدة decimal لتدعم كلًّا من العمليات الحسابية على الأرقام العشرية غير المقرّبة الدقيقة (تسمى في بعض الأحيان العمليات الحسابية على الأعداد ذات الفاصلة الثابتة fixed-point arithmetics) والعمليات الحسابية على الأعداد ذات الفاصلة العائمة المقرّبة.
* صمّمت [[الوحدات في بايثون|وحدة]] decimal لتدعم كلًّا من العمليات الحسابية على الأرقام العشرية غير المقرّبة الدقيقة (تسمى في بعض الأحيان العمليات الحسابية على الأعداد ذات الفاصلة الثابتة fixed-point arithmetics) والعمليات الحسابية على الأعداد ذات الفاصلة العائمة المقرّبة.
يتمحور تصميم وحدة decimal على ثلاثة مفاهيم أساسية: العدد العشري، السياق context الخاص بالعملية الحسابية، والإشارة signal.
يتمحور تصميم [[الوحدات في بايثون|وحدة]] decimal على ثلاثة مفاهيم أساسية: العدد العشري، السياق context الخاص بالعملية الحسابية، والإشارة signal.


العدد العشري غير قابل للتغيير immutable، ويمتلك إشارة، وأعداد coefficient وأسًّا. وللحفاظ على الأعداد الاعتبارية لا تحذف اللغة الأصفار الأخيرة في الرقم. تضمّ الأعداد العشرية decimals كذلك قيمًا خاصّة مثل <code>Infinity</code>، و <code>‎-Infinity</code> و <code>NaN</code>، وتميّز أيضًا بين القيمتين <code>‎-0</code> و <code>‎+0</code>.
العدد العشري غير قابل للتغيير immutable، ويمتلك إشارة، وأعداد coefficient وأسًّا. وللحفاظ على الأعداد الاعتبارية لا تحذف اللغة الأصفار الأخيرة في الرقم. تضمّ الأعداد العشرية decimals كذلك قيمًا خاصّة مثل <code>Infinity</code>، و <code>‎-Infinity</code> و <code>NaN</code>، وتميّز أيضًا بين القيمتين <code>‎-0</code> و <code>‎+0</code>.


يمثّل سياق العمليات الحسابية بيئة تحدّد الدقة، وقواعد التقريب، وحدود الأسس exponents، ورايات flags تحدّد نتائج العمليات، ومفعّلات المصائد trap enablers تحدّد ما إذا كانت الإشارة تعامل معاملة الاستثناءات exceptions. تقدّم اللغة خيارات التقريب التالية: <code>‎ROUND_CEILING، ROUND_DOWN، ROUND_FLOOR، ROUND_HALF_DOWN، ROUND_HALF_EVEN، ROUND_HALF_UP، ROUND_UP، ROUND_05UP‎.</code>
يمثّل سياق العمليات الحسابية بيئة تحدّد الدقة، وقواعد التقريب، وحدود الأسس exponents، ورايات flags تحدّد نتائج العمليات، ومفعّلات المصائد trap enablers تحدّد ما إذا كانت الإشارة تعامل معاملة [[الاستثناءات في بايثون|الاستثناءات exceptions]]. تقدّم اللغة خيارات التقريب التالية: <code>‎ROUND_CEILING، ROUND_DOWN، ROUND_FLOOR، ROUND_HALF_DOWN، ROUND_HALF_EVEN، ROUND_HALF_UP، ROUND_UP، ROUND_05UP‎.</code>


الإشارات هي مجموعة من الشروط الاستثنائية التي تظهر أثناء إجراء العمليات الحسابية. ويمكن تجاهل هذه الإشارات، أو عدّها مصدرًا للمعلومات، أو معاملتها كاستثناءات وذلك حسب الحاجة. تقدّم اللغة الإشارات التالية في وحدة decimal:
الإشارات هي مجموعة من الشروط الاستثنائية التي تظهر أثناء إجراء العمليات الحسابية. ويمكن تجاهل هذه الإشارات، أو عدّها مصدرًا للمعلومات، أو معاملتها [[الاستثناءات في بايثون|كاستثناءات]] وذلك حسب الحاجة. تقدّم اللغة الإشارات التالية في [[الوحدات في بايثون|وحدة]] decimal:


<code>Underflow</code> و <code>Overflow</code> و <code>Subnormal</code> و <code>Rounded</code> و <code>Inexact</code> و <code>DivisionByZero</code> و <code>InvalidOperation</code> و <code>Clamped</code> و <code>FloatOperation</code>.
<code>Underflow</code> و <code>Overflow</code> و <code>Subnormal</code> و <code>Rounded</code> و <code>Inexact</code> و <code>DivisionByZero</code> و <code>InvalidOperation</code> و <code>Clamped</code> و <code>FloatOperation</code>.
سطر 58: سطر 58:
راجع أيضًا: مواصفات IBM العامة للعمليات الحسابية على الأعداد العشرية، [http://speleotrove.com/decimal/decarith.html والمواصفات العامة للعمليات الحسابية على الأعداد العشرية.]
راجع أيضًا: مواصفات IBM العامة للعمليات الحسابية على الأعداد العشرية، [http://speleotrove.com/decimal/decarith.html والمواصفات العامة للعمليات الحسابية على الأعداد العشرية.]


= استخدام وحدة decimal =
= استخدام [[الوحدات في بايثون|وحدة]] decimal =
لاستخدام وحدة decimal يجب في البداية استيرادها، واستعراض السياق الحالي باستخدام الدالة <code>getcontext()</code>‎ وتعيين قيم جديدة لمقدار الدقة والتقريب والمصائد المفعّلة enabled traps، مثال:<syntaxhighlight lang="python3">
لاستخدام [[وحدة]] decimal يجب في البداية استيرادها، واستعراض السياق الحالي باستخدام [[الدوال في بايثون|الدالة]] <code>getcontext()</code>‎ وتعيين قيم جديدة لمقدار الدقة والتقريب والمصائد المفعّلة enabled traps، مثال:<syntaxhighlight lang="python3">
>>> from decimal import *
>>> from decimal import *


سطر 71: سطر 71:


>>> getcontext().prec = 7 # تعيين مقدار جديد للدقة
>>> getcontext().prec = 7 # تعيين مقدار جديد للدقة
</syntaxhighlight>يمكن بناء نسخ الكائن decimal من الأعداد الصحيحة، أو السلاسل النصية، أو [[الأعداد العشرية floats]] أو [[الصفوف tuples]]. عند استخدام الأعداد الصحيحة أو العشرية لبناء نسخة الكائن تجري عملية تحويل القيمة نفسها إلى النوع decimal. تتضمن الأعداد العشرية decimal قيمًا خاصّة مثل <code>NaN</code> وهي اختصار "Not a number"، وقيمة ما لانهاية الموجبة والسالبة، و ‎<code>-0</code>.
</syntaxhighlight>يمكن بناء نسخ [[الكائنات في بايثون|الكائن]] decimal من [[الأعداد الصحيحة في بايثون|الأعداد الصحيحة]]، أو [[السلاسل النصية في بايثون|السلاسل النصية]]، أو [[الأعداد العشرية floats]] أو [[الصفوف tuples في بايثون|الصفوف tuples]]. عند استخدام الأعداد الصحيحة أو العشرية لبناء نسخة الكائن تجري عملية تحويل القيمة نفسها إلى النوع decimal. تتضمن الأعداد العشرية decimal قيمًا خاصّة مثل <code>NaN</code> وهي اختصار "Not a number"، وقيمة ما لانهاية الموجبة والسالبة، و ‎<code>-0</code>.


== مثا ==
== مثا ==
سطر 109: سطر 109:
Decimal('-Infinity')
Decimal('-Infinity')


</syntaxhighlight>في حال التقاط إشارة <code>FloatOperation</code> يؤدي المزج بين نوعي الأعداد العشرية decimals وfloats في بناء نسخة الكائن أو في معاملات المقارنة إلى إطلاق استثناء:<syntaxhighlight lang="python3">
</syntaxhighlight>في حال التقاط إشارة <code>FloatOperation</code> يؤدي المزج بين نوعي الأعداد العشرية decimals وfloats في بناء نسخة الكائن أو في [[معاملات المقارنة في بايثون|معاملات المقارنة]] إلى إطلاق استثناء:<syntaxhighlight lang="python3">
>>> c = getcontext()
>>> c = getcontext()


سطر 158: سطر 158:
Decimal('5.85988')
Decimal('5.85988')


</syntaxhighlight>تطلق اللغة الاستثناء <code>InvalidOperation</code> عند تجاوز الحد المسموح به لدى إنشاء العدد العشري:<syntaxhighlight lang="python3">
</syntaxhighlight>تطلق اللغة [[الاستثناءات في بايثون|الاستثناء]] <code>InvalidOperation</code> عند تجاوز الحد المسموح به لدى إنشاء العدد العشري:<syntaxhighlight lang="python3">
>>>
>>>


سطر 227: سطر 227:




</syntaxhighlight>يمكن أيضًا استخدام بعض الدوال الرياضية مع الأعداد العشرية:<syntaxhighlight lang="python3">
</syntaxhighlight>يمكن أيضًا استخدام بعض [[الدوال الرياضية في بايثون|الدوال الرياضية]] مع الأعداد العشرية:<syntaxhighlight lang="python3">
>>> getcontext().prec = 28
>>> getcontext().prec = 28


سطر 257: سطر 257:
</syntaxhighlight>تتواصل الدالة <code>getcontenxt()‎</code> مع السياق الحالي - كما هو مبين في أعلاه - وتتيح تعديل الخيارات حسب الحاجة، وهذه الطريقة ملائمة لمعظم التطبيقات. يمكن أيضًا إنشاء سياقات بديلة عند الحاجة إلى ذلك باستخدام المشيّد <code>Context()‎</code>، وتستخدم الدالة <code>setcontext()</code>‎ لتفعيل السياق البديل.
</syntaxhighlight>تتواصل الدالة <code>getcontenxt()‎</code> مع السياق الحالي - كما هو مبين في أعلاه - وتتيح تعديل الخيارات حسب الحاجة، وهذه الطريقة ملائمة لمعظم التطبيقات. يمكن أيضًا إنشاء سياقات بديلة عند الحاجة إلى ذلك باستخدام المشيّد <code>Context()‎</code>، وتستخدم الدالة <code>setcontext()</code>‎ لتفعيل السياق البديل.


وبحسب المعايير التي تعتمدها اللغة، تقدّم وحدة decimal سياقين قياسيين جاهزين للاستخدام هما <code>BasicContext</code> و <code>ExtendedContext</code>. السياق الأوّل مفيد جدًّا في عملية التنقيح debugging لأنّ معظم المصائد تكون مفعّلة:<syntaxhighlight lang="python3">
وبحسب المعايير التي تعتمدها اللغة، تقدّم [[الوحدات في بايثون|وحدة]] decimal سياقين قياسيين جاهزين للاستخدام هما <code>BasicContext</code> و <code>ExtendedContext</code>. السياق الأوّل مفيد جدًّا في عملية التنقيح debugging لأنّ معظم المصائد تكون مفعّلة:<syntaxhighlight lang="python3">
>>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN)
>>> myothercontext = Context(prec=60, rounding=ROUND_HALF_DOWN)


سطر 312: سطر 312:
</syntaxhighlight>يبيّن مدخل flags أنّ القيمة التقريبية للعدد pi مقرّبة (تخلّصت اللغة من الأرقام التي تتجاوز مقدار دقة السياق) وأن النتيجة غير دقيقة (أي أنّ بعض الأعداد التي تم تجاهلها ليست أصفارًا).
</syntaxhighlight>يبيّن مدخل flags أنّ القيمة التقريبية للعدد pi مقرّبة (تخلّصت اللغة من الأرقام التي تتجاوز مقدار دقة السياق) وأن النتيجة غير دقيقة (أي أنّ بعض الأعداد التي تم تجاهلها ليست أصفارًا).


يمكن تعيين مصائد مفردة باستخدام القاموس في حقل traps الخاص بالسياق:<syntaxhighlight lang="python3">
يمكن تعيين مصائد مفردة باستخدام [[القواميس في بايثون|القاموس]] في حقل traps الخاص بالسياق:<syntaxhighlight lang="python3">
>>> setcontext(ExtendedContext)
>>> setcontext(ExtendedContext)


سطر 336: سطر 336:
== مصادر ==
== مصادر ==
* صفحة [https://docs.python.org/3/library/decimal.html Decimal fixed point and floating point arithmetic] في توثيق بايثون الرسمي.
* صفحة [https://docs.python.org/3/library/decimal.html Decimal fixed point and floating point arithmetic] في توثيق بايثون الرسمي.
[[تصنيف:Python]]
[[تصنيف:Python Types]]

مراجعة 20:42، 20 فبراير 2018


تتيح وحدة decimal إجراء حسابات سريعة على الأعداد العشرية مع ضمان التقريب الصحيح.

>>> import decimal

>>> Decimal(10)

Decimal('10')

>>> Decimal('3.14')

Decimal('3.14')

>>> Decimal(3.14)

Decimal('3.140000000000000124344978758017532527446746826171875')

تتفوق هذه الوحدة على نوع الأعداد العشرية float بعدة ميزات:

  • العدد العشري decimal "يستند إلى نموذج أعداد عشرية ذات فاصلة عائمة يراعي الاستخدام البشري ويلتزم بمبدأ أساسي هو أنّه يجب أن توفّر الحواسيب عمليات حسابية تعمل بنفس الطريقة التي يتعلّمها الناس في المدارس" - حسب مواصفات العمليات الحسابية التي تجرى على الأعداد العشرية decimal.
  • يمكن تمثيل الأعداد العشرية decimal بدقّة، أما الأرقام مثل 1.1 و 2.2 فلا تمثل تمثيلًا دقيقًا في النظام الثنائي للأعداد ذات الفاصلة العائمة. ولا يتوقع المستخدم أن تعطي العملية الحسابية ‎1.1 + 2.2‎ النتيجة 3.3000000000000003 كما هو الحال مع الأعداد في النظام الثنائي للأعداد ذات الفاصلة العائمة.
  • تحافظ الأعداد العشرية decimal على الدقة عند إجراء العمليات الحسابية، ففي هذا النظام يكون ناتج العمليات التالية: ‎0.1 + 0.1 + 0.1 - 0.3 هو الصفر، أما في النظام الثنائي للفاصلة العائمة يكون الناتج 5.5511151231257827e-017. صحيح أن هذا الرقم قريب جدًّا من الصفر، ولكن تعيق هذه الفروقات إجراء عمليات مقارنة دقيقة للمساواة إلى جانب أنّ هذه الفروقات يمكن أن تتزايد مع الاستمرار في إجراء العمليات الحسابية؛ لذا يفضل استخدام النوع decimal في التطبيقات المحاسبية التي تتطلّب إجراء مقارنات مساواة صارمة.
  • تعتمد وحدة decimal مفهوم الأعداد المعنوية significant؛ لذا فإنّ ناتج العملية ‎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 في بايثون بالاعتماد على المعايير المعروفة، ويعرض النوع float جزءًا بسيطًا من هذه المعايير، في حين أنّ وحدة decimal تعرض جميع الأجزاء المطلوبة ضمن هذه المعايير. ويمكن للمبرمج - عند الحاجة - أن يسيطر بصورة تامة على عمليات التقريب والتعامل مع الإشارات signals، ويمكن كذلك فرض عمليات حسابية دقيقة ومضبوطة باستخدام استثناءات توقف تنفيذ أي عملية حسابية غير دقيقة.
  • صمّمت وحدة decimal لتدعم كلًّا من العمليات الحسابية على الأرقام العشرية غير المقرّبة الدقيقة (تسمى في بعض الأحيان العمليات الحسابية على الأعداد ذات الفاصلة الثابتة fixed-point arithmetics) والعمليات الحسابية على الأعداد ذات الفاصلة العائمة المقرّبة.

يتمحور تصميم وحدة decimal على ثلاثة مفاهيم أساسية: العدد العشري، السياق context الخاص بالعملية الحسابية، والإشارة signal.

العدد العشري غير قابل للتغيير immutable، ويمتلك إشارة، وأعداد coefficient وأسًّا. وللحفاظ على الأعداد الاعتبارية لا تحذف اللغة الأصفار الأخيرة في الرقم. تضمّ الأعداد العشرية decimals كذلك قيمًا خاصّة مثل Infinity، و ‎-Infinity و NaN، وتميّز أيضًا بين القيمتين ‎-0 و ‎+0.

يمثّل سياق العمليات الحسابية بيئة تحدّد الدقة، وقواعد التقريب، وحدود الأسس exponents، ورايات flags تحدّد نتائج العمليات، ومفعّلات المصائد trap enablers تحدّد ما إذا كانت الإشارة تعامل معاملة الاستثناءات exceptions. تقدّم اللغة خيارات التقريب التالية: ‎ROUND_CEILING، ROUND_DOWN، ROUND_FLOOR، ROUND_HALF_DOWN، ROUND_HALF_EVEN، ROUND_HALF_UP، ROUND_UP، ROUND_05UP‎.

الإشارات هي مجموعة من الشروط الاستثنائية التي تظهر أثناء إجراء العمليات الحسابية. ويمكن تجاهل هذه الإشارات، أو عدّها مصدرًا للمعلومات، أو معاملتها كاستثناءات وذلك حسب الحاجة. تقدّم اللغة الإشارات التالية في وحدة decimal:

Underflow و Overflow و Subnormal و Rounded و Inexact و DivisionByZero و InvalidOperation و Clamped و FloatOperation.

لكل راية هناك trap enabler، وعندما ظهور إشارة يتم تعيين القيمة 1 للراية الخاصة بها، وبعد ذلك إن تم تعيين القيمة 1 لـ trap enabler تطلق اللغة استثناءً. تبقى قيمة الرايات ثابتة ويجب على المستخدم إعادة تعيين قيمتها قبل مراقبة الحسابات مرة أخرى.

راجع أيضًا: مواصفات IBM العامة للعمليات الحسابية على الأعداد العشرية، والمواصفات العامة للعمليات الحسابية على الأعداد العشرية.

استخدام وحدة decimal

لاستخدام وحدة decimal يجب في البداية استيرادها، واستعراض السياق الحالي باستخدام الدالة getcontext()‎ وتعيين قيم جديدة لمقدار الدقة والتقريب والمصائد المفعّلة enabled traps، مثال:

>>> 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 من الأعداد الصحيحة، أو السلاسل النصية، أو الأعداد العشرية floats أو الصفوف tuples. عند استخدام الأعداد الصحيحة أو العشرية لبناء نسخة الكائن تجري عملية تحويل القيمة نفسها إلى النوع decimal. تتضمن الأعداد العشرية decimal قيمًا خاصّة مثل NaN وهي اختصار "Not a number"، وقيمة ما لانهاية الموجبة والسالبة، و ‎-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 يؤدي المزج بين نوعي الأعداد العشرية decimals وfloats في بناء نسخة الكائن أو في معاملات المقارنة إلى إطلاق استثناء:

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

تحدّد الأعداد المعنوية للعدد العشري الجديد عن طريق عدد الأرقام المدخلة فقط، ويظهر تأثير مقدار الدقة والتقريب عند إجراء العمليات الحسابية فقط.

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

تطلق اللغة الاستثناء InvalidOperation عند تجاوز الحد المسموح به لدى إنشاء العدد العشري:

>>>

>>> Decimal("1e9999999999999999999")

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

تغيير في الإصدار 3.3

تتفاعل الأعداد العشرية decimals بصورة جيدة مع الأنواع الأخرى للبيانات في بايثون. إليك بعض الأمثلة على ذلك:

>>>

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

يمكن أيضًا استخدام بعض الدوال الرياضية مع الأعداد العشرية:

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

تتواصل الدالة getcontenxt()‎ مع السياق الحالي - كما هو مبين في أعلاه - وتتيح تعديل الخيارات حسب الحاجة، وهذه الطريقة ملائمة لمعظم التطبيقات. يمكن أيضًا إنشاء سياقات بديلة عند الحاجة إلى ذلك باستخدام المشيّد Context()‎، وتستخدم الدالة setcontext()‎ لتفعيل السياق البديل. وبحسب المعايير التي تعتمدها اللغة، تقدّم وحدة decimal سياقين قياسيين جاهزين للاستخدام هما BasicContext و ExtendedContext. السياق الأوّل مفيد جدًّا في عملية التنقيح debugging لأنّ معظم المصائد تكون مفعّلة:

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

تمتلك السياقات كذلك رايات إشارة signal flags لمراقبة الحالات الاستثنائية التي تطرأ في أثناء إجراء الحسابات. تبقى الأعلام مفعّلة إلى حين إلغائها يدويًا؛ لذا يفضّل إلغاء الأعلام قبل أي مجموعة من العمليات الحسابية التي تخضع للمراقبة، وذلك باستخدام التابع 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 في معظم البرامج دفعة واحدة باستخدام حلقة تكرارية. وبعد تعيين السياق وإنشاء الأعداد العشرية تعالج اللغة البيانات بنفس الطريقة التي تعالج بها الأنواع الرقمية الأخرى.

مصادر