print('Natija:', x*2)
O`nli sonlarning ikkiliq sanoq sistemasidagi ko`rinishi cheksiz raqamlardan iborat bo`lishi mumkinligi bunday sonlarni yahlitlashga va buning oqibatida aniqlikning yo`qolishiga olib keladi. Buning oldini olish uchun sonlarni Decimal() da satr shaklida yozish tavsiya qilinadi:
Decimal('1.23456').
Zarur hollarda str() funktsiyasidan foydalanish mumkin. Masalan,
Decimal(str(3**0.5 / 2))
ifodaning natijasi '0.8660254037844386' tarzida bo`ladi.
Sonlarni Decimal tipiga kortej shaklida ham uzatish mumkin. Bu kortej umumiy ko`rinishda quyidagicha yozilishi mumkin:
(ishora, (raqam, ..., digit), mantissa),
Bu yerda ishora musbat son uchun ‑0, manfiy sonlar uchun ‑ 1. Masalan:
>>> Decimal((0, (1, 2, 3, 4, 5, 6), -5))
Decimal('1.23456')
Sonlarni yahlitlashda kerakli raqamlar sonini quantize() metodi yordamida ko`rsatish mumkin:
Decimal('1.51567').quantize(Decimal('1.11'), rounding = ROUND_DOWN)
Decimal('1.51567').quantize(Decimal('1.11'), rounding = ROUND_UP)
Kontekstlar – bu arifmetik amallarni bajarish muhiti demakdir. Ular ammallarni qanday aniqlikda hisoblash va yahlitlash hamda qanday signallarni istisnoli vaziyat deb hisoblash, qaysilarini inkor qilish qoidalarini belgilab beradi. Kontekstning maydonlari quyidagi ma’nolarni anglatadi:
prec — arifmetik amallar aniqligini belgilaydi va u [0, MAX_PREC] oqaliqda bo’lishi mumkin;
rounding — yahlitlash rejimini o’rnatadi;
traps va flags maydonlari o’z ichiga signallar ro’yhati hamda ularni nazorat qilish alomatlarini oladi;
Emin va Emax maydonlari daraja ko’rsatkichlarini belgilab beradi. Emin ning qiymatlari [MIN_EMIN, 0], Emax ning qiymatlari esa [0, MAX_EMAX] diapazonda yotadi;
Capitals maydoni daraja belgisini ekranga qanday shaklda chiqarish kerakligini ko’rsatadi. To’g’ridan-to’g’ri bu qiymat 1 ga teng va u “E”, 0 esa “e” harfiga mos keladi;
Clamp maydoni 1 yoki 0 ga teng bo’ladi. Agar 1 bo’lsa, o’nli sonning e eksponentasi [Emin - prec + 1, Emax - prec + 1] diapazonda bo’ladi. Agar clamp=0 bo’sa, daraja ko’rsatkichi Emax dan katta bo’la olmaydi.
Har bir jarayon o’z kontekstiga ega bo’lib, zarur hollarda uni getcontext() yoki setcontext() metodlari bilan o’zgartirish mumkin. Buning uchun kontekstning maydonlarini ehtiyojga ko’ra qayta belgilanadi. Masalan,
my_context = Context(prec = 9, Emax = 99999).
Agar qaysidir maydon ko’rsatilmagan bo’lsa, bu qiymatlar kontekstning DefaultContext qiymatlaridan olinadi. Bayroqchalar ko’rsatilmagan yoki tushirib qoldirilgan bo’lsa, bu holat bayroqchalarning tozalanishiga olib keladi:
my_context = Context(prec = 3, rounding = ROUND_DOWN)
setcontext(my_context)
print(1/8, Decimal(1)/Decimal(8))
print(1/15, Decimal(1)/Decimal(15))
print(180/13, Decimal(180)/Decimal(13))
Shuningdek, Decimal moduli ikkita tayyor kontkestni taklif etadi: BasicContext va ExtendedContext:
from decimal import *
print(BasicContext)
print(ExtendedContext)
Agar BasicContext ga e`tibor qaratilsa, unda dasturlarni otladka qilishda foydali bo`lgan ko`plab istisnoli vaziyatlar nazarda tutilganini ko`rish mumkin. Masalan, BasicContext da
Decimal(1)/Decimal(0)
buyrug’i hatolikka ishora qilinsa, ExtendedContext da hech qanday istisnoli vaziyatni qayd etilmaydi.
Hatoliklarni kuzatib borish uchun bayroqchalar asosida ishlovchi mahsus signallar mavjud. Bu bayroqchalar tushirib qo`yilmaguncha faol hisoblanadi. YUqoridagi ExtendedContext ning flags=[] hususiyatiga e`tibor bering. Bu holat uchun :
Decimal(1)/Decimal(3)
amali '0.333333333' natijani beradi. Ana shu bayroqchalarning flags=[Inexact, Rounded], traps=[] holati uchun)
Decimal(1)/Decimal(0)
buyrug’i 'Infinity' natijani qaytaradi.
from decimal import *
setcontext(ExtendedContext)
print(getcontext())
print(Decimal(1)/Decimal(3))
print(getcontext())
print(Decimal(1)/Decimal(0))
Bayroqchalarni tushirib qo`yish uchun clear_flags() metodidan foydalanish mumkin:
getcontext().clear_flags().
Istisnoli vaziyatlarni tutib qolish uchun traps parametri qiymatlarini o`zgartirishga to`g’ri keladi:
from decimal import *
getcontext().traps[Rounded] = 1
print(Decimal(1)/Decimal(16))
print(Decimal(1)/Decimal(17))
YUqoridagi kodda Rounded faollashtirilganidan keyin, Decimal(1)/Decimal(16) buyrug’i hatoosiz bajarildi, chunki natija prec da ko`rsatilgan diapazonga tushadi va yahlitlashga ehtiyoj yo`q. Decimal(1)/Decimal(17) amalining natijasini esa yahlitlashga to`g’ri keladi va bu holat istisnoli vaziyatni yuzaga keltiradi.
Agar FloatOperation signali 1 ga o`zgartirilgan bo`lsa, haqiqiy sonlarni Decimal tipiga o`tkazish hatolikni yuzagagkeltirishi mumkin:
>>> getcontext().traps[FloatOperation] = 1
>>> Decimal(0.1)
Traceback (most recent call last):
File "", line 1, in
decimal.FloatOperation: []
Context metodining argumenti satr raqamlar ketma⁃ketligilan iborat bo`lmagan hollarni qayta ishlashga imkon beradi. To`g’ridan‑to`g’ri bu parametrning qiymati ‑ None bo`lib, bunday satrlarni NaN ga aylantiradi:
>>> Decimal('dssd')
Decimal('NaN')
SHunday qilib, istisnoli vaziyatlarni tutib qolish orqali ko`plab kutilmagan signallarni tutib qolish evaziga ishonchli dasturlar ishlab chiqish mumkin bo`ladi.
Decimal tipidagi sonlar ustida int va float tipidagi sonlar uchun ruhsat berilgan barcha amallarni bajarish mumkin. Faqat Decimal tipida '%' (qoldiq) operatorini bajarganda natija va bo`linuvchining ishorasi bir hil bo`ladi:
from decimal import *
print('Natural sonlar uchun :', -10%4, 10 % -4)
print('Decimal sonlar uchun ', Decimal(-10) % Decimal(4))
print('Decimal sonlar uchun ', Decimal(10) % Decimal(-4))
Bitta matematik ifodada Decimal, float hamda fractions.Fraction kasrlar tipidagi ma`lumotlarning uchrashi mumkin emas. Agar FloatOperation bayroqchasi o`rnatilmagan bo`lsa, faqat taqqoslash amalidagina bunday tipdagi sonlardan birgalikda foydalanish mumkin:
from decimal import *
print(Decimal('1.2') == 1.2)
from fractions import Fraction
print(Decimal('1.2') == Fraction(6, 5))
Do'stlaringiz bilan baham: |