ماژول fractions به ما امکان میدهد rational numbers را بسازیم و با آنها کار کنیم: کسرهایی با یک صورت صحیح تقسیم بر یک مخرج صحیح.
برای مثال، میتوانیم 2/3 را بهصورت یک کسر دقیق ذخیره کنیم، نه بهصورت مقدار تقریبی float یعنی 0.6666...
برخلاف اعداد int، float و complex، کسرها شکل نوشتاری مستقیمی ندارند.
با این حال، سازندهی کسر کاملاً انعطافپذیر است.
بدیهیترین حالت این است که دو عدد صحیح بگیرد. عوامل مشترک بهطور خودکار حذف میشوند و کسر به «سادهترین شکل» خود تبدیل میشود (کوچکترین اعداد صحیحی که کسر را بهدرستی نمایش میدهند):
>>> from fractions import Fraction
>>> f1 = Fraction(2, 3) # 2/3
>>> f1
Fraction(2, 3)
>>> f2 = Fraction(6, 9)
>>> f2
Fraction(2, 3) # automatically simplified
>>> f1 == f2
True
سازندهی کسر میتواند یک نمایش رشتهای را هم تجزیه کند:
>>> f3 = Fraction('2/3')
>>> f3
Fraction(2, 3)
همچنین میتواند با پارامترهای float کار کند، اما ممکن است بهدلیل ماهیت تقریبی نمایش داخلی مقدار اعشاری بهصورت دودویی به مشکل بخورد.
برای اطلاعات بیشتر دربارهی این مسئلهی نمایش، وبسایت 0.30000000000000004 و بخش Floating Point Arithmetic: Issues and Limitations در مستندات Python را ببینید.
برای گرفتن نتیجهای مطمئنتر هنگام استفاده از اعداد اعشاری همراه با کسرها، متد <fraction>.limit_denominator() در دسترس است.
.limit_denominator() میتواند در صورت داشتن نیازهای خاص، یک پارامتر صحیح بگیرد، اما حتی مقدار پیشفرض (max_denominator=1000000) هم میتواند خوب کار کند و یک تقریب ساده و قابلقبول به دست دهد.
>>> Fraction(1.2)
Fraction(5404319552844595, 4503599627370496)
>>> Fraction(1.2).limit_denominator()
Fraction(6, 5)
عملگرهای arithmetic operators معمول + - * / ** با کسرها هم کار میکنند، همانطور که با سایر انواع عددی کار میکنند.
میتوان اعداد صحیح و Fractionهای دیگر را هم در محاسبه وارد کرد و نتیجه یک Fraction خواهد بود.
وارد کردن یک float در عبارت باعث خروجی float میشود که در پی آن احتمالاً دقت از دست میرود.
>>> Fraction(2, 3) + Fraction(1, 4) # addition
Fraction(11, 12)
>>> Fraction(2, 3) * Fraction(6, 5) # multiply fractions
Fraction(4, 5)
>>> Fraction(2, 3) * 6 / 5 # fraction with integers
Fraction(4, 5)
>>> Fraction(2, 3) * 1.2 # fraction with float -> float
0.7999999999999999
>>> Fraction(2, 3) ** 2 # exponentiation with integer
Fraction(4, 9)
کسرها برای حفظ دقت در محاسبات میانی عالی هستند، اما ممکن است برای خروجی نهایی چیزی نباشند که میخواهید.
میتوان صورت و مخرج را جداگانه یا بهصورت یک تاپل به دست آورد (tuples در یک مفهوم دیگر و در زمانی بعدتر بررسی خواهد شد):
>>> Fraction(2, 3).numerator
2
>>> Fraction(2, 3).denominator
3
>>> Fraction(2, 3).as_integer_ratio()
(2, 3)
توابع عددی استاندارد مختلف Python هم همان نتیجهای را میدهند که از کار با انواع int و float انتظار دارید:
>>> round(Fraction(11, 3))
4
>>> from math import floor, ceil
>>> floor(Fraction(11, 3))
3
>>> ceil(Fraction(11, 3))
4
>>> float(Fraction(11, 3))
3.6666666666666665