Mashina xotirasida qiymatlarni saqlash

Biz mashina xotirasida har doim qiymat(son)larni saqlaymiz undan boshqa narsani emas va o’z navbatida bu sonlarni ham biz o’nlik sanoq tizimida emas, balki ikkilik sanoq tizimida saqlaymiz. Keling birinchi sanoq tizimi nima ekanligini bilib olaylik. Biz kundalik turmushimizda ishlatadigan sanoq tizimi 10 lik sanoq tizimi deyiladi, chunki unda faqat 10 belgi bor. Ya’ni ular: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 va biz ularni raqamlar deymiz. Hamda shu raqamlardan foydalanib har xil sonlarni yozamiz. Lekin kompyuterda biz bu sanoq tizmidan foydalana olmaymiz, uning o’rniga biz ikkilik sanoq tizimidan foydalanamiz.

Keling birinchi quyidagi ikkita katakdan iborat bo’lgan 2-bitli xotirani qaraylik. Biz bitlarning joyini sanashni o’ngdan boshlaymiz, chunki soning oldiga nol raqami qo’shilsa uning qiymati o’zgarmaydi, bu esa keyinchalik bizga umumiy holda qulaylik beradi.

1-bit

0-bit

0

0

0

1

1

0

1

1

Demak, bizda ikki bit bo’lsa, u joyga biz 0 va 1 larning 4 ta turli xil ko’rinishini yoza olamiz. Bu ko’rinishlar 10 lik sanoq tizimida esa 0, 1, 2, 3 lardir:

1-bit

0-bit

ikki bitdagi soning 10 lik qiymati

0

0

0

0

1

1

1

0

2

1

1

3

Umumiy qoida esa \(2^{bitlar\,soni}\) bo’ladi. Masalan, 3 bitli joyga biz \(2^3=8\) gacha bo’lgan sonlarni yozishimiz mumkin bo’ladi yoki 4 bitlisiga esa \(2^4=16\) gacaha.

Lekin biz oldindan bizga qanday son berilishini bilmasak, u holda songa ko’proq xotiradan joy ajratamiz. Agar son biz ajratgan joydan kichik bitlarga sig’sa, unda uning oldiga keraklicha 0 qo’shamiz. Masalan, 23 soni bu o’nlikda desak, unda uning ikkilik ko’rinishi 10111 bo’ladi. Agar shu soni 32 bitli xotiraga saqlamoqchi bo’lsak, uning oldiga 27 ta nol qo’shamiz, ya’ni

00000000000000000000000000010111

Agar kiritilgan son biz ajratgan bitlardan oshib ketsa, masalan, 8 bitli xotiraga 257 soni yozmoqchi bo’lsak, u holda biz muammolar paydo bo’ladi. Bu narsalar turli dasturlash tillarida farqli ravishda yechilgan. Pythonning asl holatida biz bunday muammolarni ko’rmaymiz, lekin kutubxonalar bilan ishlagan bu narsaga duch kelamiz.

Keling endi qanday qilib manifiylikni ifodalashni ko’raylik. Misol uchun son -23 bo’lsin, unda ishorani ifodalash uchun biz ajratgan bitlarning oxirgisiga 1 qo’yish bilan shu soni manifiyligini bildiramiz, ya’ni:

10000000000000000000000000010111

ya’ni soning manifiyligini bildirish uchun birinchi nol 1 ga aylanadi. Bu degani birinchi bit sonning manifiy yoki musbatligi uchun ajratiladi, qolgan 31 bitga esa sonning o’zini saqlaymiz. Ushbu qoidalar sababidan biz xotiradan joy olmoqchi bo’lsak, shu joyga nima yozishimiz kerakligini oldindan aytamiz aks holda qiymatlarni umumiy satr turida saqlashga to’g’iri keladi. Bu esa o’z navbatida dasturning ishlash tezligini keskin tushirib yuboradi.

Odatda ko’pchilik o’rganuvchilarda savol tug’uladi:

Nimaga biz soni ikkilik ko’rinishda saqlanishini bilishimiz kerak, chunki biz dasturlash tillari bilan ishlayotganimizda ular biz o’zgaruvchiga o’zlashtirgan qiymatni to’g’iridan-to’g’iri ikkilik ko’rinishga o’tkazsa?

Bu jarayon shunday bo’lishi rost, faqat biz nega saqlanayotgan qiymatlarning turlarni va ayniqsa biz haqiqiy sonlar bilan amallar bajarayotganimizda qiymatlarni yuqolishini ham bilishimiz kerak. Buni esa faqat sonlarni qanday xotirada joylashtirishga bog’liqligi asosida tushunishimiz mumkin. Masalan, \(-\frac{200}{3}\) soni 32 bitli xotirada IEEE 754 standart bo’yicha quyidagicha bo’ladi. Biz qo’shimcha ushbu misolda soddaroq holni qaraymiz, ya’ni bu haqiqiy standartdagi berilgan hamma hollarni o’z ichiga olmaydi. Berilgan 32 bitni 3 ta qismga bo’lamiz:

  1. ishora (musbat yoki manifiy uchun) 1 bit;

  2. exponenta uchun 8 bit;

  3. hamda, mantissa uchun qolgan 23 bit.

Ishora

Exponenta

Mantissa

1

8

23

  1. Berilgan son manifiy bo’lgani uchun, birinchi bit ga 1 yozamiz.

  2. Exponentani quyidagicha hisoblaymiz. Birinchi soni quyidagi ko’rinishda yozamiz: \(\frac{2}{3}10^2\). Keyin esa, 10 sonining darajasidagi 2 sonini ikkilik sanoq sistemasiga o’tkazib, uni Exponentagaga yozamiz. \(2_{10}\rightarrow 10_{2}\). Lekin bizda 8 bit bor, shuning uchun \(10_{2}\) oldiga 6 nol qo’shamiz, ya’ni \(00000010_{2}\).

  3. Matnissa qismi \(\frac{2}{3}\) ikkilik sanoq sistemasiga o’tkazish orqali amalga oshirladi. Buning uchun shu soni 2 ko’paytiramiz va butun qismidagi soni (0 yoki 1) saqlab qo’yamiz. Quyidagi jadvalda ushbu jarayon batafsil keltirilgan.

Son

ko’paytiriluvchi son (2)

Ikkilik ko’rinish

\(1+\frac{1}{3}\)

\(\frac{2}{3}*2\)

1

\(0+\frac{2}{3}\)

\(\frac{1}{3}*2\)

10

\(1+\frac{1}{3}\)

\(\frac{2}{3}*2\)

101

\(0+\frac{2}{3}\)

\(\frac{1}{3}*2\)

1010

\(1+\frac{1}{3}\)

\(\frac{2}{3}*2\)

10101

\(1+\frac{1}{3}\)

\(\frac{2}{3}*2\)

10101010101010101010101

Yuqoridagi takrorlash 23 ta raqam bo’lgunicha davom etadi va sonning qolgan qismi tashlab yuboriladi. Ko’rib turganimizdek, biz xotiraga kichkina sonni ham aniq(to’liq) holda saqlay olmas ekanmiz. Shuning uchun sonlarning turlari bilan xotirada ishlayotganda, har bir qismdan maqsadli foydalanish zarur bo’ladi. Hamda ular o’rtasidagi har xil amallarda (+, -, *, /) har doim yaxlitlash xatoligi mavjud bo’ladi va bu o’z navbatida ba’zi vaqtlarda tanlagan matematik modelimiz xatoliklarga olib keladi.