از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
گرد کردن اعداد در پایتون
سرفصلهای مطلب
استفاده از رایانه برای انجام ریاضیات نسبتاً پیچیده یکی از دلایلی است که این دستگاه در ابتدا توسعه یافت. تا زمانی که اعداد صحیح و جمع، تفریق و ضرب منحصراً در محاسبات دخالت دارند، همه چیز خوب است. به محض اینکه اعداد ممیز شناور یا کسرها و همچنین تقسیمات وارد بازی می شوند، کل موضوع را به شدت پیچیده می کند.
به عنوان یک کاربر معمولی، ما به طور کامل از این مسائلی که در پشت صحنه اتفاق میافتند آگاه نیستیم و ممکن است نتایج نسبتاً شگفتانگیز و احتمالاً نادقیق برای محاسبات خود داشته باشیم. بهعنوان توسعهدهندگان، ما باید اطمینان حاصل کنیم که اقدامات مناسبی در نظر گرفته میشوند تا به رایانه دستور دهیم به روش درست کار کند.
در زندگی روزمره ما از سیستم اعشاری که مبتنی است استفاده می کنیم روی عدد 10. کامپیوتر از سیستم باینری که پایه 2 است استفاده می کند و در داخل مقادیر را به صورت دنباله ای از 1 و 0 ذخیره و پردازش می کند. ارزشهایی که ما با آنها کار میکنیم باید دائماً بین دو نمایش تغییر شکل دهند. همانطور که در مستندات پایتون:
… اکثر کسرهای اعشاری را نمی توان دقیقاً به صورت کسری باینری نشان داد. نتیجه این است که، به طور کلی، اعداد ممیز شناور اعشاری که وارد میکنید، تنها با اعداد ممیز شناور باینری که واقعاً در دستگاه ذخیره میشوند، تقریبی دارند.
این رفتار منجر به نتایج شگفت انگیزی در اضافات ساده می شود، همانطور که در اینجا نشان داده شده است:
فهرست 1: عدم دقت در اعداد ممیز شناور
>>> s = 0.3 + 0.3 + 0.3
>>> s
0.8999999999999999
همانطور که در اینجا می بینید، خروجی نادرست است، زیرا باید 0.9 شود.
لیست 2 حالت مشابهی را برای قالب بندی یک عدد ممیز شناور برای 17 رقم اعشار نشان می دهد.
فهرست 2: قالب بندی یک عدد ممیز شناور
>>> format(0.1, '.17f')
'0.10000000000000001'
همانطور که ممکن است از مثال های بالا آموخته باشید، برخورد با اعداد ممیز شناور کمی مشکل است و برای دستیابی به نتیجه صحیح و به حداقل رساندن خطاهای محاسباتی به اقدامات بیشتری نیاز دارد. گرد کردن مقدار می تواند حداقل برخی از مشکلات را حل کند. یک امکان داخلی است round()
عملکرد (برای جزئیات بیشتر در مورد استفاده از آن به زیر مراجعه کنید):
فهرست 3: محاسبه با مقادیر گرد شده
>>> s = 0.3 + 0.3 + 0.3
>>> s
0.8999999999999999
>>> s == 0.9
False
>>> round(0.9, 1) == 0.9
True
به عنوان یک جایگزین، می توانید با ماژول ریاضی کار کنید، یا به طور صریح با کسرهایی که به عنوان دو مقدار (عدم و مخرج) ذخیره شده اند، به جای مقادیر ممیز شناور گرد و نسبتاً غیر دقیق کار کنید.
به منظور ذخیره مقادیر مانند دو ماژول پایتون اعشاری و کسر وارد بازی شوید (نمونه های زیر را ببینید). اما ابتدا اجازه دهید نگاهی دقیق تر به اصطلاح “گرد کردن” داشته باشیم.
گرد کردن چیست؟
در چند کلمه، process گرد کردن یعنی:
… جایگزین کردن (مقدار) با عددی متفاوت که تقریباً برابر با عدد اصلی است، اما نمایش کوتاهتر، سادهتر یا واضحتری دارد.
Source: https://en.wikipedia.org/wiki/Rounding
اساساً، با کوتاه کردن مقدار دقیق محاسبه شده، عدم دقت را اضافه می کند. در بیشتر موارد این کار با حذف ارقام بعد از نقطه اعشار انجام می شود، برای مثال از 3.73 تا 3.7، 16.67 تا 16.7 یا 999.95 تا 1000.
چنین کاهشی به دلایل مختلفی انجام می شود – به عنوان مثال، صرفه جویی در فضا هنگام ذخیره مقدار، یا صرفاً برای حذف ارقام استفاده نشده. علاوه بر این، دستگاههای خروجی مانند نمایشگرهای آنالوگ یا ساعتها میتوانند مقدار محاسبهشده را تنها با دقت محدود نشان دهند و به دادههای ورودی تنظیمشده نیاز دارند.
به طور کلی، دو قانون نسبتاً ساده برای گرد کردن اعمال می شود، ممکن است آنها را از مدرسه به خاطر بسپارید. ارقام 0 تا 4 منجر به گرد کردن و اعداد 5 تا 9 منتهی به گرد کردن. جدول زیر مجموعه ای از موارد استفاده را نشان می دهد.
| original value | rounded to | result |
|----------------|--------------|--------|
| 226 | the ten | 230 |
| 226 | the hundred | 200 |
| 274 | the hundred | 300 |
| 946 | the thousand | 1,000 |
| 1,024 | the thousand | 1,000 |
| 10h45m50s | the minute | 10h45m |
روش های گرد کردن
ریاضیدانان انواع مختلفی از روشهای گرد کردن را برای حل مشکل گرد کردن توسعه دادهاند. این شامل کوتاه کردن ساده، گرد کردن به بالا، گرد کردن به پایین، گرد کردن نیمه به بالا، گرد کردن نیمه به پایین، و همچنین گرد کردن نیمه به دور از صفر و گرد کردن از نیمه به زوج است.
به عنوان مثال، گرد کردن نصف دور از صفر است توسط کمیسیون اروپا اعمال می شود روی امور اقتصادی و مالی هنگام تبدیل ارزها به یورو چندین کشور مانند سوئد، هلند، نیوزیلند و آفریقای جنوبی از قاعده ای به نام «گرد کردن پول نقد»، «گردش پنی» یا «گردش سوئدی» پیروی می کنند.
(گرد کردن وجه نقد) زمانی اتفاق می افتد که حداقل واحد حساب کوچکتر از کمترین ارزش فیزیکی ارز باشد. مبلغ قابل پرداخت برای تراکنش نقدی به نزدیکترین مضرب حداقل واحد ارز موجود گرد می شود، در حالی که تراکنش های پرداخت شده به روش های دیگر گرد نمی شوند.
Source: https://en.wikipedia.org/wiki/Cash_rounding
در آفریقای جنوبی، از سال 2002، گرد کردن وجه نقد به نزدیکترین 5 سنت انجام شده است. به طور کلی، این نوع گرد کردن در مورد پرداخت های الکترونیکی غیر نقدی اعمال نمی شود.
در مقابل، گرد کردن از نیمه به زوج، استراتژی پیشفرض پایتون، NumPy، و پانداها است و توسط داخلی استفاده میشود. round()
عملکردی که قبلا ذکر شد. این روش متعلق به دسته روشهای دور به نزدیکترین است و بهعنوان گرد کردن همگرا، گرد آماری، گرد کردن هلندی، گرد گاوسی، گرد کردن زوج و فرد و گرد کردن بانکداران نیز شناخته میشود. این روش در تعریف شده است IEEE 754 و به گونه ای عمل می کند که «اگر قسمت کسری از x
پس 0.5 است y
نزدیکترین عدد صحیح زوج است x
فرض بر این است که “احتمالات یک تساوی در یک مجموعه داده که به پایین یا به بالا گرد می شود برابر است” که معمولاً در عمل چنین است. اگرچه این استراتژی کاملاً کامل نیست منجر به نتایج قابل ملاحظه ای می شود.
جدول زیر مثال های عملی گرد کردن این روش را ارائه می دهد:
| original value | rounded to |
|----------------|------------|
| 23.3 | 23 |
| 23.5 | 24 |
| 24.0 | 24 |
| 24.5 | 24 |
| 24.8 | 25 |
| 25.5 | 26 |
توابع پایتون
پایتون دارای تابع داخلی است round()
که در مورد ما بسیار مفید است. دو پارامتر را می پذیرد – مقدار اصلی و تعداد ارقام بعد از نقطه اعشار. فهرست زیر استفاده از روش را برای یک، دو و چهار رقم بعد از نقطه اعشار نشان می دهد.
فهرست 4: گرد کردن با تعداد مشخصی از ارقام
>>> round(15.45625, 1)
15.5
>>> round(15.45625, 2)
15.46
>>> round(15.45625, 4)
15.4563
اگر این تابع را بدون پارامتر دوم فراخوانی کنید، مقدار به یک عدد صحیح کامل گرد می شود.
فهرست 5: گرد کردن بدون تعداد مشخصی از ارقام
>>> round(0.85)
1
>>> round(0.25)
0
>>> round(1.5)
2
در صورتی که به نتایج کاملا دقیق نیاز نداشته باشید، مقادیر گرد شده به خوبی کار می کنند. به این واقعیت توجه داشته باشید که مقایسه مقادیر گرد شده نیز می تواند یک کابوس باشد. در مثال زیر آشکارتر خواهد شد – مقایسه مقادیر گرد شده بر اساس روی قبل از گرد کردن، و پس از گرد کردن.
اولین محاسبه از لیست 6 حاوی مقادیر از پیش گرد شده است و گرد کردن را قبل از اضافه کردن مقادیر به بالا توصیف می کند. محاسبه دوم شامل یک خلاصه پس گرد است که به معنای گرد کردن پس از جمع است. متوجه خواهید شد که نتیجه مقایسه متفاوت است.
فهرست 6: پیش گرد در مقابل پس گرد
>>> round(0.3, 10) + round(0.3, 10) + round(0.3, 10) == round(0.9, 10)
False
>>> round(0.3 + 0.3 + 0.3, 10) == round(0.9, 10)
True
ماژول های پایتون برای محاسبات نقطه شناور
چهار ماژول محبوب وجود دارد که می تواند به شما کمک کند تا به درستی با اعداد ممیز شناور برخورد کنید. این شامل math
ماژول، numpy
ماژول، decimal
ماژول، و fractions
مدول.
را math
ماژول حول ثابت های ریاضی، عملیات ممیز شناور و روش های مثلثاتی متمرکز است. را numpy
ماژول خود را به عنوان “بسته اساسی برای محاسبات علمی” توصیف می کند و به دلیل انواع روش های آرایه معروف است. را decimal
ماژول محاسبه نقطه ثابت اعشاری و ممیز شناور و fractions
ماژول به طور خاص با اعداد گویا سروکار دارد.
ابتدا باید سعی کنیم محاسبات را بهبود ببخشیم لیست 1. مانند لیست 7 نشان می دهد، پس از وارد کردن math
ماژول می توانیم به روش دسترسی داشته باشیم fsum()
که لیستی از اعداد ممیز شناور را می پذیرد. برای اولین محاسبه تفاوتی بین داخلی وجود ندارد sum()
روش، و fsum()
روش از math
ماژول، اما برای دومی اینطور است، و نتیجه درستی را که انتظار داریم برمیگرداند. دقت بستگی دارد روی الگوریتم اصلی IEEE 754
فهرست 7: محاسبات ممیز شناور با کمک math
مدول
>>> import math
>>> sum((0.1, 0.1, 0.1))
0.30000000000000004
>>> math.fsum((0.1, 0.1, 0.1))
0.30000000000000004
>>> sum((0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1))
0.9999999999999999
>>> math.fsum((0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1))
1.0
دوم، اجازه دهید نگاهی به numpy
مدول. همراه با متد () around که مقادیر ارائه شده به عنوان یک آرایه را گرد می کند. مقادیر واحد را به همان روش پیش فرض پردازش می کند round()
روش.
به منظور مقایسه مقادیر numpy
ارائه می دهد equal()
روش. شبیه به around()
مقادیر منفرد و همچنین لیستی از مقادیر (به اصطلاح بردار) را برای پردازش می پذیرد. فهرست 8 مقایسه ای برای مقادیر تک و همچنین مقادیر گرد شده را نشان می دهد. رفتار مشاهده شده کاملاً شبیه به روش های نشان داده شده قبلی است.
فهرست 8: مقایسه مقادیر با استفاده از روش برابر از numpy
مدول
>>> import numpy
>>> print (numpy.equal(0.3, 0.3))
True
>>> print (numpy.equal(0.3 + 0.3 + 0.3 , 0.9))
False
>>> print (numpy.equal(round(0.3 + 0.3 + 0.3) , round(0.9)))
True
گزینه سه این است decimal
مدول. این نمایش اعشاری دقیق را ارائه می دهد و ارقام قابل توجه را حفظ می کند. دقت پیشفرض 28 رقم است و میتوانید این مقدار را به عددی تغییر دهید که به اندازه مشکل شما باشد. لیست 9 روش استفاده از دقت 8 رقمی را نشان می دهد.
فهرست 9: ایجاد اعداد اعشاری با استفاده از decimal
مدول
>>> import decimal
>>> decimal.getcontext().prec = 8
>>> a = decimal.Decimal(1)
>>> b = decimal.Decimal(7)
>>> a / b
Decimal('0.14285714')
اکنون، مقایسه مقادیر شناور بسیار آسانتر میشود و به نتیجهای که به دنبال آن بودیم منجر میشود.
فهرست 10: مقایسه با استفاده از decimal
مدول
>>> import decimal
>>> decimal.getcontext().prec = 1
>>> a = decimal.Decimal(0.3)
>>> b = decimal.Decimal(0.3)
>>> c = decimal.Decimal(0.3)
>>> a + b + c
Decimal('0.9')
>>> a + b + c == decimal.Decimal('0.9')
True
را decimal
ماژول همچنین دارای روشی برای گرد کردن مقادیر است – quantize(). استراتژی گرد کردن پیشفرض روی گرد کردن از نیمه به زوج تنظیم شده است و در صورت نیاز میتوان آن را به روش دیگری تغییر داد. لیست 11 استفاده از را نشان می دهد quantize()
روش. لطفاً توجه داشته باشید که تعداد ارقام با استفاده از یک مقدار اعشاری به عنوان پارامتر مشخص می شود.
فهرست 11: گرد کردن یک مقدار با استفاده از quantize()
>>> d = decimal.Decimal(4.6187)
>>> d.quantize(decimal.Decimal("1.00"))
Decimal('4.62')
آخرین اما نه کم اهمیت ترین، ما نگاهی به fractions
مدول. این ماژول به شما اجازه می دهد تا مقادیر ممیز شناور را به عنوان مثال به صورت کسری مدیریت کنید 0.3
به عنوان 3/10. این مقایسه مقادیر ممیز شناور را ساده می کند و گرد کردن مقادیر را کاملاً حذف می کند. لیست 12 روش استفاده از ماژول کسری را نشان می دهد.
فهرست 12: ذخیره و مقایسه مقادیر ممیز شناور به عنوان کسری
>>> import fractions
>>> fractions.Fraction(4, 10)
Fraction(2, 5)
>>> fractions.Fraction(6, 18)
Fraction(1, 3)
>>> fractions.Fraction(125)
Fraction(125, 1)
>>> a = fractions.Fraction(6, 18)
>>> b = fractions.Fraction(1, 3)
>>> a == b
True
علاوه بر این، دو ماژول decimal
و fractions
همانطور که در مثال بعدی نشان داده شده است می توان ترکیب کرد.
فهرست 13: کار با اعشار و کسری
>>> import fractions
>>> import decimal
>>> a = fractions.Fraction(1,10)
>>> b = fractions.Fraction(decimal.Decimal(0.1))
>>> a,b
(Fraction(1, 10), Fraction(3602879701896397, 36028797018963968))
>>> a == b
False
نتیجه
ذخیره و پردازش مقادیر ممیز شناور به درستی یک ماموریت است و نیاز به توجه زیادی برای برنامه نویسان دارد. گرد کردن مقادیر ممکن است کمک کند، اما حتماً ترتیب صحیح گرد کردن و روشی را که استفاده میکنید بررسی کنید. این در هنگام توسعه مواردی مانند نرم افزار مالی بسیار مهم است، بنابراین باید قوانین قوانین محلی را برای گرد کردن بررسی کنید.
پایتون تمام ابزارهای مورد نیاز را در اختیار شما قرار می دهد و با “باتری ها همراه است”. هک مبارک!
سپاسگزاریها
نویسنده مایل است از نظرات انتقادی زولکا هافمن هنگام تهیه این مقاله تشکر کند.
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-21 04:47:05