decimal یکی از ماژولهای پایتون به حساب میآید و شامل مجموعهای از توابع میشود که یکی از آنها تابع Decimal در پایتون است. ماژول decimal در پایتون از گرد کردن درست محاسبات ریاضی ممیز شناور پشتیبانی میکند. در این نوشتار آموزش تابع Decimal در پایتون و ماژول decimal در پایتون ارائه شده است.
درک تابع Decimal در پایتون یا همان ماژول decimal
ماژول decimal در پایتون دارای توابع مختلفی برای کنترل نوع داده عددی و اجرای محاسبات ریاضی مختلف روی آن است. با استفاده از ماژول decimlal در پایتون میتوان اعداد دسیمال (مبنای ۱۰) را به طور بهینه در طول برنامه خود مدیریت کرد. ماژول decimal در پایتون توابعی را برای کنترل و چیرگی بر مشکل دقت محاسبات در مقادیر مبنای ۱۰ (دسیمال) فراهم میکند. برای استفاده از توابع مورد نیاز باید ماژول decimal را به صورت زیر Import کرد:
import decimal
معرفی تابع Decimal در پایتون یا به بیان صحیح ماژول دسیمال
بسیاری از اعداد Decimal مثل عدد 0.1
نمایش دقیقی در ممیز شناور دودویی ندارند. در زمان استفاده از این اعداد در عملیات محاسبات ریاضی، نتیجهای حاصل میشود که انتظار آن وجود ندارد. برای مثال داریم:
x = 0.1
y = 0.1
z = 0.1
s = x + y + z
print(s)
خروجی قطعه کد فوق به صورت زیر است:
0.30000000000000004
ملاحظه میشود که در خروجی به جای عدد 0.3
، عدد 0.30000000000000004
نمایش داده شده است. برای رفع این مسئله، از کلاس یا تابع Decimal واقع در ماژول decimal
به صورت زیر استفاده میشود:
import decimal
from decimal import Decimal
x = Decimal('0.1')
y = Decimal('0.1')
z = Decimal('0.1')
s = x + y + z
print(s)
حالا خروجی به صورت زیر خواهد بود:
0.3
مشاهده میشود که با استفاده از تابع Decimal در پایتون حالا خروجی مطابق انتظار و صحیح است. ماژول decimal در پایتون از آن عملیات حسابی پشتیبانی میکند که همگان در محاسبات آموزش داده شده در مدرسه یاد گرفتهاند. برخلاف نوعهای شناور (Floats)، پایتون اعداد دسیمال (مبنای ۱۰) را به صورت دقیق نمایش میدهد و این دقت بالا وارد عملیات حسابی میشود. برای مثال عبارت زیر دقیقاً مقدار 0.0
را بازمیگرداند:
Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')
بافت یا زمینه Decimal در پایتون
Decimal همواره با بافت و زمینهای (Context) مرتبط است که جنبههای زیر را کنترل میکند:
- دقت محاسبات ریاضی
- الگوریتم گرد کردن (Rounding)
در حالت پیشفرض بافت یا زمینه به صورت «سراسری» (گلوبال | Global) است. به بیان دیگر بافت یا زمینه سراسری در پایتون زمینه پیشفرض در نظر گرفته میشود. همچنین میتوان یک زمینه موقت را ایجاد و تنظیم کرد که به صورت محلی بدون تحت تاثیر قرار دادن بافت سراسری موثر واقع خواهد شد. برای دریافت زمینه پیشفرض، میتوان تابع getcontext()
را از ماژول decimal
فراخوانی کرد:
decimal.getcontext()
تابع getcontext()
زمینه پیشفرض را بازمیگرداند که این زمینه میتواند سراسری (Global) یا محلی (Local) باشد. برای ایجاد بافت جدیدی که از بافت دیگری کپی شده است از تابع localcontext()
استفاده میشود که سینتکس آن به صورت زیر است:
decimal.localcontext(ctx=None)
تابع localcontext()
بافت جدیدی را بازمیگرداند که از بافت ctx
در صورت تعیین شدن آن کپی میشود. پس از دریافت شی زمینه (Context Object)، میتوان به تنظیمات مربوط به میزان دقت و همچنین تنظیمات گرد کردن از طریق خصیصههای prec
و rounding
به ترتیب زیر دسترسی پیدا کرد:
- ctx.prec
: دریافت یا تنظیم دقت محاسبات؛ ctx.prec
عددی از نوع صحیح با مقدار پیشفرض ۲۸ است.
- ctx.rounding
: ساز و کار دریافت یا تنظیم گرد کردن؛ این خصوصیت یک رشته با مقدار پیشفرض ‘ROUND_HALF_EVEN’
است. باید توجه داشت که برای اعداد ممیز شناور نیز میتوان از این ساز و کار گرد کردن استفاده کرد.
ساز و کارهای گرد کردن در پایتون
در پایتون ساز و کارهای گرد کردن زیر فراهم هستند:
گرد کردن | شرح |
ROUND_UP | گرد کردن با فاصله گرفتن از صفر |
ROUND_DOWN | گرد کردن به سمت صفر |
ROUND_CEILING | گرد کردن به سمت سقف (به سمت بینهایت مثبت) |
ROUND_FLOOR | گرد کردن به سمت کف (به سمت بینهایت منفی) |
ROUND_HALF_UP | گرد کردن به نزدیکترین، از صفر فاصله میگیرد. |
ROUND_HALF_DOWN | گرد کردن به نزدیکترین، به سمت صفر |
ROUND_HALF_EVEN | گرد کردن به نزدیکترین، به سمت زوج میل میکند (کمترین رقم قابل توجه) |
نحوه بدست آوردن دقت پیش فرض و گرد کردن زمینه پیش فرض
در ادامه مثالی آمده است که نشان میدهد چطور میتوان دقت پیشفرض و گرد کردن زمینه پیشفرض را بدست آورد:
import decimal
ctx = decimal.getcontext()
print(ctx.prec)
print(ctx.rounding)
خروجی کدهای فوق به صورت زیر است:
28 ROUND_HALF_EVEN
گرد کردن با ‘ROUND_HALF_EVEN’
حال مثال دیگری در ادامه آمده است که نشان میدهد ساز و کار گرد کردن با خصوصیت ‘ROUND_HALF_EVEN’
چگونه انجام میشود:
import decimal
from decimal import Decimal
x = Decimal('2.25')
y = Decimal('3.35')
print(round(x, 1))
print(round(y, 1))
خروجی به صورت زیر است:
2.2 3.4
گرد کردن با ‘ROUND_HALF_UP’
اگر شیوه گرد کردن به ‘ROUND_HALF_UP’
تغییر داده شود، نتیجه متفاوتی حاصل خواهد شد:
import decimal
from decimal import Decimal
ctx = decimal.getcontext()
ctx.rounding = decimal.ROUND_HALF_UP
x = Decimal('2.25')
y = Decimal('3.35')
print(round(x, 1))
print(round(y, 1))
خروجی کدهای فوق به صورت زیر خواهد بود:
2.3 3.4
در مثالی که در ادامه آمده، نشان داده شده است که چگونه زمینه پیشفرض باید کپی شود و ساز و کار گرد کردن به حالت ‘ROUND_HALF_UP’
تغییر کند:
import decimal
from decimal import Decimal
x = Decimal('2.25')
y = Decimal('3.35')
with decimal.localcontext() as ctx:
print('Local context:')
ctx.rounding = decimal.ROUND_HALF_UP
print(round(x, 1))
print(round(y, 1))
print('Global context:')
print(round(x, 1))
print(round(y, 1))
خروجی کدهای فوق در ادامه آمده است:
Local context: 2.3 3.4 Global context: 2.2 3.4
ملاحظه میشود که زمینه محلی تاثیری روی زمینه سراسری نمیگذارد. بعد از بلوک with
، پایتون از ساز و کار گرد کردن پیشفرض استفاده میکند.
معرفی فیلم های آموزش پایتون
تقریباً همه دورههای ویدیویی مرتبط با آموزش پایتون در قالب یک مجموعه آموزشی در پلتفرم تم آف جمعآوری شدهاند. در مجموعه آموزشهای پایتون علاوه بر دورههای مقدماتی، تکمیلی و پیشرفته، دورههای پروژه محور آموزش پایتون و سایر دورههای مربوط به کاربرد پایتون در حوزههای مختلف برنامه نویسی نیز در دسترساند. جدیدترین دوره آموزشی این مجموعه دوره آموزش پیشرفته ترفندهای پایتون است که در آن ترفندهای استفاده از تابع Decimal در پایتون هم شرح داده شدهاند. در تصویر فوق تنها برخی از دورههای آموزشی پروژهمحور مجموعه آموزش پایتون قابل مشاهده هستند.
- برای دسترسی به همه آموزش های پایتون تم آف + اینجا کلیک کنید.
سازنده Decimal در پایتون
سازنده دسیمال (Decimal Constructor) امکان ایجاد شی Decimal جدیدی را بر پایه یک مقدار فراهم میکند:
Decimal(value='0', context=None)
- مقاله موجود برای بدست آوردن درکی از مفهوم سازنده: سازنده در ++C — راهنمای کاربردی
آرگومان value
میتواند از نوع «صحیح» (Integer)، «رشتهای» (String)، «تاپل» (Tuple)، «ممیز شناور» (Float) یا شیء Decimal دیگری باشد. در صورتی که مقداری برای آگومان مربوطه تعیین نشود، مقدار پیشفرض یعنی 0
استفاده خواهد شد.
در صورتی که مقدار آرگومان value
از جنس تاپل باشد، باید شامل ۳ جزء شود:
- علامت ( 0
برای علامت مثبت و 1
برای علامت منفی)
- تاپلی شامل اعداد
- توانی از نوع صحیح
(sign, (digit1,digit2, digit3,...), exponent)
برای مثال میتوان عدد پی را به صورت زیر نوشت:
3.14 = 314 x 10^-2
در مثال فوق تاپل مربوطه همانطور که در ادامه آمده، دارای ۳ عنصر مختلف است:
- علامتش 0
است.
- رقمها (3,1,4)
هستند.
- توان هم -2
است.
بنابراین لازم است تاپل زیر به سازنده Decimal
ارجاع داده شود:
import decimal
from decimal import Decimal
x = Decimal((0, (3, 1, 4), -2))
print(x)
خروجی کدهای فوق به صورت زیر است:
3.14
ملاحظه میشود که دقت بافت دسیمال تنها عملیات ریاضی را تحت تاثیر قرار میدهد و در سازنده Decimal
موثر نیست. در ادامه مثال دیگری ارائه شده است:
import decimal
from decimal import Decimal
decimal.getcontext().prec = 2
pi = Decimal('3.14159')
radius = 1
print(pi)
area = pi * radius * radius
print(area)
وقتی از یک عدد ممیز شناور استفاده میشود که دارای بازنمایی یا نمایش شناور دودویی دقیقی نیست، سازنده Decimal نمیتواند بازنمایی دسیمال دقیقی را ایجاد کند. برای مثال داریم:
import decimal
from decimal import Decimal
x = Decimal(0.1)
print(x)
خروجی:
0.1000000000000000055511151231257827021181583404541015625
در عمل برای ساخت یک Decimal
در پایتون از رشته یا تاپل استفاده میشود.
عملیات حسابی Decimal در پایتون
کلاس Decimal
تعدادی عملیات ریاضی مثل sqrt
و log
را فراهم میکند. اگرچه، دارای تمام توابع تعریف شده در ماژول math
نیست.
وقتی توابع ماژول math
برای اعداد دسیمال مورد استفاده قرار میگیرند، پایتون قبل از انجام عملیات حسابی اشیای Decimal
را به ممیز شناور تبدیل میکند. این باعث میشود که دقت ساخته شده در اشیای دسیمال از دست برود.
پس از آشنایی مقدماتی با تابع Decimal در پایتون و درک نیاز به ماژول decimal، بهتر است در ادامه به توابع مهم ارائه شده در این ماژول پرداخته شود.
توابع ماژول Decimal در پایتون و نحوه پیاده سازی آن ها
برای تقویت و بهبود حاصل جواب، عملیات حسابی مختلف را میتوان با استفاده از تابع Decimal در پایتون یا به بیان صحیحتر، ماژول decimal پایتون روی دادههای مبنای ۱۰ (دسیمال | دهدهی) یا دادههای عددی اجرا کرد. میتوان اعداد «ممیز دسیمال» (ممیز دهدهی| Decimal Point | دهدهی اعشاری) را با استفاده از تابع Decimal در پایتون یعنی decimal.Decimal()
همانگونه تعریف کرد که پیشتر هم نشان داده شد. نحوه استفاده از این تابع به صورت زیر انجام میشود:
import decimal
variable = decimal.Decimal(decimal-number)
علاوه بر این، میتوان مقدار دقت در نتیجه محاسبات اعداد دهدهی را نیز با استفاده از تابع داخلی موجود در ماژول decimal یعنی decimal.getcontext().prec
کنترل کرد. سینتکس آن به صورت زیر است:
decimal.getcontext().prec = precision value
حال در ادامه توابعی معرفی و شرح داده شدهاند که به اجرای عملیات ریاضی دهدهی (دسیمال) به گونهای بهینه و با سرعت بالا کمک میکنند.
تابع exp() در ماژول decimal پایتون
تابع exp()
مقدار توان را محاسبه میکند. یعنی این تابع عملیات e^x
را برای عدد ورودی مشخصي از نوع اعشاری (ممیز دسیمال) محاسبه میکند. سینتکس تابع exp()
در ماژول decimal در پایتون به صورت زیر است:
decimal.Decimal(decimal-number).exp()
مثالی برای تابع exp() در ماژول decimal پایتون
برای درک بهتر نحوه استفاده از تابع exp()
در ماژول decimal پایتون مثالی در ادامه آمده است:
import decimal as d
d.getcontext().prec = 5
#Intializing with an addition operation
val = d.Decimal(12.201) + d.Decimal(12.20)
#Calculating exponential of the decimal value
exp = val.exp()
#variable with no calculations
no_math = d.Decimal(1.131231)
print("Sum: ",val)
print("Exponential: ", exp)
print(no_math)
خروجی به صورت زیر است:
Decimal Number: 24.401 3.9557E+10 1.131231000000000097571728474576957523822784423828125
ملاحظه میشود که تعداد کل رقمها در خروجی برابر با ۵ رقم است. دلیلش این است که میزان دقت در اینجا برابر با ۵ تنظیم شده است.
چیزی که باید به خاطر داشت این است که مقدار دقت محاسبات، زمانی اِعمال میشود که عملیات ریاضی روی ۲ عدد از نوع دسیمال اجرا شوند. وقتی که متغیری به طور مستقیم ایجاد میشود (مثل متغیر no_math در کدهای بالا)، میزان دقت تعیین شده موثر نخواهد بود.
تابع sqrt() در ماژول decimal پایتون برای محاسبه ریشه درجه دوم
تابع sqrt() در ماژول decimal پایتون برای محاسبه مقدار ریشه دوم عدد دسیمال ارجاع شده استفاده میشود. سینتکس و نحوه استفاده از این تابع به صورت زیر است:
decimal.Decimal(decimal-number).sqrt()
مثالی برای تابع sqrt() در ماژول decimal پایتون
در این بخش مثالی برای آموزش نحوه استفاده از تابع sqrt() در ماژول decimal پایتون ارائه شده است:
import decimal as d
d.getcontext().prec = 3
val = d.Decimal(122.20)
sqrt = val.sqrt()
print("Decimal Number: ",val)
print("Square root of the decimal number: ",sqrt)
خروجی مثال فوق به صورت زیر است:
Decimal Number: 122.2000000000000028421709430404007434844970703125 Square root of the decimal number: 11.1
باز هم لازم است توجه شودکه چگونه مقدار اعلان شده حاوی عدد دسیمال کامل است، در حالی که مقدار محاسبه شده از میزان دقت تعیین شده یعنی دقت ۳ رقمی تبعیت میکند.
برای مشاهده عملیات ریاضی بیشتر، پیشنهاد میشود مقاله آشنایی با ماژول Math در پایتون را مطالعه کنید.
توابع لگاریتمی در ماژول decimal پایتون
در ماژول دسیمال پایتون توابع زیر برای محاسبه مقادیر لگاریتمی اعداد دهدهی فراهم شدهاند:
- decimal.ln()
- decimal.log10()
تابع decimal.ln()
مقدار لگاریتم طبیعی عدد دهدهی را مطابق زیر بازمیگرداند:
decimal.Decimal(decimal-number).ln()
تابع decimal.log10()
برای محاسبه مقدار log با مبنای ۱۰ از عدد دسیمالی استفاده میشود که به آن ارجاع شده است. سینتکس آن در ادامه آمده است:
decimal.Decimal(decimal-number).log10()
مثالی برای توابع لگاریتمی ماژول decimal پایتون
مثال مربوطه در ادامه آمده است:
import decimal as d
d.getcontext().prec = 2
val = d.Decimal(122.20)
log = val.ln()
print("Natural log value of the decimal number: ",log)
log_10 = val.log10()
print("Log value with base 10 of the decimal number: ",log_10)
خروجی:
Natural log value of the decimal number: 4.8 Log value with base 10 of the decimal number: 2.1
تابع compare() در ماژول decimal پایتون
تابع decimal.compare()
دو عدد دهدهی یا همان دسیمال را مقایسه میکند و مقادیر را بسته به شرایط به صورت زیر خروجی میدهد:
- اگر اولین عدد دسیمال از عدد دسیمال دوم کوچکتر باشد، مقدار -1
را بازمیگرداند.
- اگر اولین عدد دسیمال بزرگتر از دومین عدد دسیمال باشد، مقدار 1
را بازمیگرداند.
- اگر هر دو مقدار دسیمال برابر باشند، مقدار 0
بازگردانده خواهد شد.
مثالی برای تابع compare() در ماژول decimal پایتون
مثال مربوطه در ادامه آمده است:
import decimal as d
valx = d.Decimal(122.20)
valy = d.Decimal(123.01)
print("Value 1: ",valx)
print("Value 2: ",valy)
compare = valx.compare(valy)
print(compare)
خروجی:
Value 1: 122.2000000000000028421709430404007434844970703125 Value 2: 123.0100000000000051159076974727213382720947265625 -1
تابع copy_abs() در ماژول decimal پایتون
تابع decimal.copy_abs() مقادیر قدر مطلق عدد دهدهی علامتداری که به آن ارجاع شده است را بازمیگرداند. سینتکس این تابع در ماژول decimal پایتون به صورت زیر است:
decimal.Decimal(signed decimal number).copy_abs()
مثالی برای تابع copy_abs() در ماژول decimal پایتون
مثال مربوط به این تابع به صورت زیر است:
import decimal as d
valx = d.Decimal(-122.20)
print("Value 1: ",valx)
absolute = valx.copy_abs()
print("Absolute value of the given decimal number: ",absolute)
خروجی مثال فوق در ادامه آمده است:
Value 1: -122.2000000000000028421709430404007434844970703125 Absolute value of the given decimal number: 122.2000000000000028421709430404007434844970703125
توابع Max و Min در ماژول decimal پایتون
ماژول decimal پایتون حاوی توابع زیر برای محاسبه مقادیر کمینه و بیشینه اعداد دهدهی یا همان دسیمال در پایتون است:
- تابع min()
: کمینه دو مقدار دهدهی را باز میگرداند.
- تابع max()
: بیشینه ۲ مقدار دسیمال یا همان دهدهی را بازمیگرداند.
سینتکس هر یک از این دو تابع در ادامه آمده است:
#Syntax for min() function-
decimal1.min(decimal2)
#Syntax for max() function-
decimal1.max(decimal2)
مثالی برای توابع Max و Min در ماژول decimal پایتون
این مثال در ادامه ملاحظه میشود:
import decimal as d
valx = d.Decimal(122.20)
valy = d.Decimal(123.01)
print("Value 1: ",valx)
print("Value 2: ",valy)
min_val = valx.min(valy)
print("The minimum of the two values: ",min_val)
max_val = valx.max(valy)
print("The maximum of the two values: ",max_val)
خروجی:
Value 1: 122.2000000000000028421709430404007434844970703125 Value 2: 123.0100000000000051159076974727213382720947265625 The minimum of the two values: 122.2000000000000028421709430 The maximum of the two values: 123.0100000000000051159076975
عملیات منطقی با ماژول دسیمال در پایتون
ماژول decimal در پایتون حاوی مجموعهای از توابع داخلی برای اجرای عملیات منطقی روی اعداد دسیمال (دهدهی) است که از جمله آنها میتوان به XOR ،OR ،AND و سایر موارد اشاره کرد.
- تابع logical_and()
: این تابع عملیات AND منطقی را روی ۲ عدد دهدهی انجام میدهد و نتیجه را بازمیگرداند.
- تابع logical_or()
: این تابع عملیات OR منطقی را روی ۲ عدد اعشاری دسیمال انجام میدهد و نتیجه را خروجی میدهد.
- تابع logical_xor()
: این تابع عملیات XOR منطقی را روی ۲ عدد دسیمال اجرا میکند و نتیجه را بازمیگرداند.
سینتکس هر یک از توابع فوق در ادامه آمده است:
#Syntax for logical_and() function-
decimal1.logical_and(decimal2)
#Syntax for logical_or() function-
decimal1.logical_or(decimal2)
#Syntax for logical_xor() function-
decimal1.logical_xor(decimal2)
مثالی برای عملیات منطقی با ماژول دسیمال در پایتون
این مثال در ادامه ملاحظه میشود:
import decimal as d
valx = d.Decimal(1001)
valy = d.Decimal(1111)
print("Value 1: ",valx)
print("Value 2: ",valy)
AND = valx.logical_and(valy)
print("The logical AND value of the two decimals: ",AND)
OR = valx.logical_or(valy)
print("The logical OR value of the two decimals: ",OR)
XOR = valx.logical_xor(valy)
print("The logical XOR value of the two decimals: ",XOR)
خروجی مثال فوق در ادامه آمده است:
Value 1: 1001 Value 2: 1111 The logical AND value of the two decimals: 1001 The logical OR value of the two decimals: 1111 The logical XOR value of the two decimals: 110
جمعبندی
در ادامه فهرستی برای جمعبندی مواردی ارائه شده است که در این نوشتار شرح داده شدند:
- از ماژول decimal
در پایتون زمانی استفاده میشود که بخواهیم پشتیبانی از محاسبات اعشاری ممیز شناور سریع و به درستی گرد شده وجود داشته باشد.
- از کلاس Decimal
که در ماژول decimal
موجود است میتوان برای ایجاد اشیای Decimal از رشتهها، اعداد صحیح و تاپلها استفاده کرد.
- اعداد Decimal
دارای بافت یا زمینهای هستند که ساز و کار میزان دقت و گرد کردن به وسیله آن کنترل میشود.
- کلاس Decimal
دارای تمام متدهای تعریف شده در ماژول math
نیست. اگرچه، باید از متدهای محاسباتی Decimal در صورت در دسترس بودن استفاده کرد.