IlmHamroh
JavaScript Full-stack/1-qism. Kompyuter, fayllar va terminal7/40-dars13 daqiqa
Mundarija (30)

Sonlar ichkarida: manfiy sonlar, kasr sonlar va bitli amallar

Qisqacha: Kompyuter har bir son uchun cheklangan miqdorda bit ajratadi. Son unga sig'masa, "toshib" ketadi va kutilmagan qiymatga aylanadi. Manfiy sonlar maxsus usulda (two's complement) saqlanadi, kasr sonlar esa yaxlitlanadi — shuning uchun 0.1 + 0.2 aniq 0.3 bo'lmaydi. Bitli amallar esa sonning har bir biti bilan alohida ishlash imkonini beradi.

Bu darsda

  • Kompyuter sonlarga nega cheklangan joy ajratishini va toshish (overflow) nima ekanini tushunasiz.
  • Manfiy son xotirada qanday yozilishini hisoblay olasiz.
  • Mashhur 0.1 + 0.2 = 0.30000000000000004 sababini tushuntira olasiz.
  • Pulni hisoblashda bu muammodan qanday qochishni bilasiz.
  • Bitli amallar (AND, OR, XOR, NOT, surish) bilan ruxsatlarni tekshira olasiz.

Oldin bilishingiz kerak: Nega 0 va 1: ikkilik sanoq sistemasi, O'n oltilik va sakkizlik sanoq sistemalari — ayniqsa chmod dagi r = 4, w = 2, x = 1.

1. Nega bu kerak?

Qog'ozda biz -15 deb minus qo'yamiz yoki 3.14 deb nuqta qo'yamiz. Kompyuter xotirasida esa "minus" yoki "nuqta" uchun alohida katak yo'q. U yerda faqat bitlar — 0 va 1.

Shuning uchun muhandislar minus va nuqtani ham bitlar bilan yozish qoidalarini o'ylab topgan. Bu qoidalarni bilmasangiz, dasturda g'alati narsalarga duch kelasiz:

  • Do'kon dasturida 0.1 + 0.2 qo'shilganda ekranga 0.30000000000000004 chiqadi.
  • Hisoblagich eng katta qiymatiga yetgach, birdan nolga yoki manfiy songa aylanib qoladi.

Bular xato emas, balki kompyuter sonlarni qanday saqlashining natijasi. Keling, birma-bir ko'ramiz.

2. Har bir songa cheklangan joy

2.1 Qutichalar

Kompyuter son uchun oldindan aniq miqdorda joy ajratadi: 8, 16, 32 yoki 64 bit. Buni qutichaga o'xshatish mumkin: quti qanday bo'lsa, unga shuncha son sig'adi.

Ikkilik sanoq sistemasi darsidan bilamiz: 8 bitga 0 dan 255 gacha son sig'adi. Kattaroq qutilar:

Bitlar soni Eng katta son (faqat musbat)
8 bit 255
16 bit 65 535
32 bit 4 294 967 295 (~4.3 milliard)
64 bit ~18 kvintillion (18 ta nol bilan)

Faqat musbat sonlar saqlanadigan bunday qutilar ishorasiz (unsigned) deyiladi.

2.2 Toshish (overflow)

8 bitlik qutida 255 turibdi deylik. Unga 1 qo'shsak nima bo'ladi?

text
   11111111   (255)
 + 00000001   (1)
 ──────────
 1 00000000   (256 — lekin 9 ta bit kerak!)

Natijaga 9 ta bit kerak, qutida esa faqat 8 ta joy bor. Eng chapdagi 1 sig'maydi va tashlab yuboriladi. Qutida 00000000, ya'ni 0 qoladi.

Son o'z qutisiga sig'magani uchun kutilmagan qiymatga aylanishi toshish (overflow) deyiladi.

Hayotdan misol: eski mashinalardagi probeg hisoblagichi 6 xonali bo'ladi. 999 999 km dan keyin u 000 000 ni ko'rsatadi — mashina yangi bo'lib qolmagan, shunchaki hisoblagichda joy tugagan.

Tekshirib ko'ring: 8 bitlik ishorasiz qutida 250 turibdi. Unga 10 qo'shilsa, qutida nima qoladi?

Javob

250 + 10 = 260. Lekin 8 bitga ko'pi bilan 255 sig'adi. Toshish sodir bo'ladi: 256 "aylanib o'tadi" va 260 − 256 = 4 qoladi. Xuddi probeg hisoblagichi 999 999 dan keyin boshidan boshlagandek.

3. Manfiy sonlar qanday saqlanadi?

3.1 Retsept: teskari qilib, 1 qo'shish

Manfiy sonlarni saqlash uchun zamonaviy kompyuterlar two's complement ("ikkigacha to'ldirish") usulini ishlatadi. Retsepti uch qadam.

Musbat 5 dan −5 yasaymiz:

  1. 5 ni 8 bitda yozamiz: 00000101.
  2. Hamma bitlarni teskari qilamiz — 0 ni 1 ga, 1 ni 0 ga: 11111010.
  3. Natijaga 1 qo'shamiz: 11111011.

Mana, 11111011 — xotiradagi −5.

Qadam Bitlar
+5 00000101
Teskari qilindi 11111010
1 qo'shildi (−5) 11111011

Bu usulda eng chapdagi bit sonning ishorasini ko'rsatadi: 0 — musbat, 1 — manfiy. U ishora biti (sign bit) deyiladi.

3.2 Manfiy sonni qanday o'qish mumkin?

Eng oson yo'l: 8 bitli sonda eng chapdagi xonani −128 deb hisoblang, qolganlarini odatdagidek qo'shing.

text
Xona:   -128   64   32   16    8    4    2    1
Bit:       1    1    1    1    1    0    1    1

−128 + 64 + 32 + 16 + 8 + 2 + 1 = −128 + 123 = −5. To'g'ri!

Shuning uchun 8 bitli ishorali (signed) son −128 dan +127 gacha bo'ladi:

  • eng kichigi 10000000 = −128;
  • eng kattasi 01111111 = 64 + 32 + 16 + 8 + 4 + 2 + 1 = 127.

3.3 Nega aynan shu usul?

Chunki bu usulda protsessorga ayirish uchun alohida qurilma kerak emas. Ayirish — manfiy sonni qo'shish. 5 + (−5) ni hisoblaymiz:

text
   00000101   (+5)
 + 11111011   (−5)
 ──────────
 1 00000000   (0)

To'qqizinchi bit qutiga sig'madi va tashlab yuborildi. Qolgani 00000000, ya'ni 0. Oddiy qo'shish amali ayirishni ham bajardi! CPU darsidagi ALU uchun bu juda qulay.

Tekshirib ko'ring: 11111111 ishorali 8 bitli son sifatida nechaga teng?

Javob

−128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = −128 + 127 = −1. E'tibor bering: ishorasiz son sifatida xuddi shu bitlar 255 edi. Bitlar bir xil — ularni qanday o'qishga kelishganimiz farq qiladi.

4. Ishorali sonlarda toshish

Ishorali 8 bitli songa ham joy chegarasi bor. +127 ga 1 qo'shsak:

text
   01111111   (+127)
 + 00000001   (+1)
 ──────────
   10000000   (−128!)

Eng katta musbat son birdan eng kichik manfiy songa aylandi. Bu ham toshish.

Real hayotda bu hazil emas:

  • YouTube, 2014-yil. "Gangnam Style" klipi ko'rishlar soni 32 bitli ishorali qutining chegarasiga — 2 147 483 647 ga yaqinlashdi. YouTube hisoblagichni oldindan 64 bitga o'tkazib qo'yishga majbur bo'ldi.
  • 2038-yil muammosi. Ko'p tizimlar vaqtni "1970-yildan beri o'tgan soniyalar" sifatida 32 bitli songa yozadi. 2038-yil 19-yanvarda bu son chegaradan oshadi. Shuning uchun zamonaviy tizimlar vaqtni 64 bitda saqlaydi.

5. Kasr sonlar nega aniq emas?

5.1 Mashhur holat

Dasturchilar orasida mashhur misol bor. Quyidagi JavaScript kodi 0.1 + 0.2 ni hisoblaydi. (JavaScript'ni hali o'rganmadik — faqat izohdagi natijaga qarang. === belgisi "aynan tengmi?" degan savol.)

js
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false

Kompyuter qo'shishni bilmaydimi? Biladi. Muammo — sonni saqlashda.

5.2 1/3 ni eslang

O'nlikda 1/3 ni yozib ko'ring: 0.333333... — cheksiz davom etadi. Qog'ozga qancha 3 yozsangiz ham, bu aniq 1/3 bo'lmaydi. Qayerdadir to'xtab, yaxlitlaysiz.

Ikkilik sistemada esa 0.1 (ya'ni 1/10) xuddi shunday "cheksiz" son:

text
0.1 (o'nlikda) = 0.000110011001100110011... (ikkilikda)

0011 bo'lagi abadiy takrorlanadi. Kompyuterda esa bitlar soni cheklangan. Oxirgi bitlarda yaxlitlash sodir bo'ladi. 0.1 ham, 0.2 ham ozgina yaxlitlangan holda saqlanadi. Ularni qo'shganda o'sha kichik xatolar yig'ilib, 0.30000000000000004 chiqadi.

5.3 IEEE 754: kasr son qanday saqlanadi?

Deyarli barcha kompyuterlar kasr sonlarni IEEE 754 degan xalqaro standart bo'yicha saqlaydi. Bunday sonlar suzuvchi nuqtali son (floating-point, qisqasi float) deyiladi.

G'oyasi maktabdagi "standart ko'rinish"ga o'xshaydi: 1500 = 1.5 × 10³. Kompyuter ham sonni ikki qismga bo'ladi — raqamlar va daraja. Faqat 10 emas, 2 ning darajasini ishlatadi.

64 bitlik float shunday taqsimlanadi:

Qism Bitlar Nima saqlaydi
Ishora 1 Musbat yoki manfiy
Daraja 11 Nuqta qayerda turishi
Raqamlar (mantissa) 52 Sonning o'zi

Bunday son taxminan 15–17 ta raqamni aniq saqlaydi. Undan keyingisi yaxlitlanadi. Shuning uchun juda katta butun sonlarda ham aniqlik yo'qoladi:

js
console.log(9007199254740993); // 9007199254740992

Oxirgi raqam 3 edi, 2 bo'lib qoldi — sonda raqamlar juda ko'p, hammasiga joy yetmadi. JavaScript'dagi sonlar aynan shu 64 bitlik float. Bu mavzuga JavaScript Number darsida qaytamiz.

5.4 Pulni qanday hisoblash kerak?

Onlayn do'kon yoki to'lov tizimi yozsangiz, pulni kasr son sifatida hisoblamang. Bir necha ming amaldan keyin tiyinlar farq qila boshlaydi.

Eng ishonchli qoida: pulni eng kichik butun birlikda saqlang.

  • 19.99 dollar o'rniga 1999 sent deb saqlang.
  • So'mda — tiyinda: 15 000 so'm = 1 500 000 tiyin.
  • Foydalanuvchiga ko'rsatishda 100 ga bo'lib chiqarasiz.

Butun sonlarni qo'shishda yaxlitlash xatosi bo'lmaydi. Masalan, Payme to'lov tizimi ham dasturchilardan summani tiyinda qabul qiladi. Bu mavzuni pul va aniq hisob-kitob darsida chuqur ko'ramiz.

Tekshirib ko'ring: Nega 0.5 + 0.25 kompyuterda aniq 0.75 chiqadi, 0.1 + 0.2 esa aniq chiqmaydi?

Javob

0.5 = 1/2 va 0.25 = 1/4 — ikkilikda "chiroyli" sonlar: 0.1 va 0.01. Ular cheklangan bitlarga aniq sig'adi. 0.1 esa 1/10, ikkilikda cheksiz takrorlanadi va yaxlitlanadi. Xuddi o'nlikda 1/2 = 0.5 aniq yozilgani, 1/3 esa yozilmagani kabi.

6. Bitli amallar

6.1 To'rt asosiy amal

Bitli amallar (bitwise operations) — ikki sonning bitlarini xonama-xona solishtiradigan amallar. Oldin sonlar ikkilikka o'tkaziladi, keyin har bir ustun alohida hisoblanadi.

Amal Belgisi Qoidasi (har bir ustun uchun)
AND ("va") & Ikkala bit ham 1 bo'lsa → 1
OR ("yoki") | Kamida bittasi 1 bo'lsa → 1
XOR ("faqat bittasi") ^ Bitlar har xil bo'lsa → 1
NOT ("teskari") ~ Har bir bitni teskari qiladi

Keling, 5 va 3 ustida sinaymiz. 5 = 101, 3 = 011:

text
      AND      OR       XOR
      101      101      101
      011      011      011
      ───      ───      ───
      001      111      110
      = 1      = 7      = 6
  • AND: faqat eng o'ng ustunda ikkalasi ham 1 → 001 = 1.
  • OR: har ustunda kamida bitta 1 bor → 111 = 7.
  • XOR: ikkinchi va uchinchi ustun har xil → 110 = 6.

NOT esa bitta son bilan ishlaydi. ~5 natijasi −6 chiqadi. Nega? 8 bitda 5 = 00000101, teskarisi 11111010. Chap xonani −128 deb o'qish usuli bilan: −128 + 122 = −6.

6.2 Surish (shift)

  • Chapga surish (<<) — hamma bitlarni chapga suradi, o'ngga 0 qo'shadi. 5 << 1: 101 → 1010 = 10. Sonni 2 ga ko'paytirdi.
  • O'ngga surish (>>) — bitlarni o'ngga suradi, eng o'ngdagisi tushib qoladi. 5 >> 1: 101 → 10 = 2. 2 ga bo'lib, qoldiqni tashladi.

O'nlikda ham shunday: 35 ning oxiriga 0 qo'shsangiz, 350 bo'ladi — 10 ga ko'paydi. Ikkilikda esa 2 ga ko'payadi.

6.3 Bitlar bilan ruxsatlar

Hex darsidagi chmod ni eslang: o'qish = 4 (100), yozish = 2 (010), bajarish = 1 (001). Har bir ruxsat — o'z biti. Bunday "har bit — bitta ha/yo'q belgisi" usuli bit bayroqlari (bit flags) deyiladi.

Ruxsatlarni birlashtirish — OR bilan:

text
  100   (o'qish, 4)
| 010   (yozish, 2)
  ───
  110   (6 — o'qish va yozish)

Ruxsat borligini tekshirish — AND bilan. Foydalanuvchining ruxsati 6 (110). U faylni bajara oladimi?

text
  110   (ruxsatlar, 6)
& 001   (bajarish, 1)
  ───
  000   (0 — demak, ruxsat yo'q)

Natija 0 bo'lsa — ruxsat yo'q. 0 dan boshqa son chiqsa — bor. 6 & 4 = 100 = 4, demak o'qish ruxsati bor.

JavaScript'da bu shunday yoziladi (hozircha faqat qarang, natijalar izohda):

js
const OQISH = 4;
const YOZISH = 2;
const BAJARISH = 1;

const ruxsat = OQISH | YOZISH;
console.log(ruxsat); // 6
console.log(ruxsat & BAJARISH); // 0
console.log(ruxsat & OQISH); // 4

const — qiymatga nom berish usuli, uni o'zgaruvchilar darsida o'rganamiz. Bitli amallarning JavaScript'dagi ishlatilishi esa alohida darsda keladi.

Tekshirib ko'ring: 4 | 1 va 7 & 2 nechaga teng?

Javob

4 | 1: 100 va 001 → 101 = 5 (o'qish va bajarish). 7 & 2: 111 va 010 → 010 = 2 (7 da yozish biti bor, shuning uchun natija 0 emas).

7. Ko'p uchraydigan xatolar

7.1 Pulni kasr son bilan hisoblash

Bank yoki do'kon ilovasida summani kasr son bilan qo'shib borsangiz, oxirida bir necha tiyin farq chiqadi. Buxgalteriya hisobi to'g'ri kelmaydi. Yechim: har doim eng kichik birlikda (tiyin, sent) butun son bilan hisoblang.

7.2 Kasr sonlarni "aynan teng" deb solishtirish

0.1 + 0.2 ni 0.3 bilan aynan solishtirsangiz, false chiqadi — garchi matematikada ular teng bo'lsa ham. Kasr sonlarni solishtirishda "juda yaqinmi?" deb tekshirish kerak. Buni qanday qilishni JavaScript Number darsida ko'ramiz.

7.3 Hisoblagichga kichik quti tanlash

Ko'rishlar, yuklab olishlar yoki ID raqamlar soni vaqt o'tgan sari o'sib boradi. Ularga kichik quti (masalan, 32 bit) tanlansa, bir kun toshish sodir bo'ladi — xuddi YouTube'dagidek. O'sib boradigan hisoblagichlar uchun 64 bit tanlang.

7.4 & bilan && ni adashtirish

JavaScript'da && degan boshqa belgi ham bor — u "va" shartlari uchun (masalan, "yoshi 18 dan katta va pasporti bor"). Bitta & esa bitlar bilan ishlaydi. Ular o'xshash, lekin vazifasi har xil. && ni mantiqiy operatorlar darsida o'rganamiz.

8. Mashqlar

1-mashq (oson): OR amali

4 | 1 ni hisoblang. 4 ikkilikda 100, 1 esa 001.

Javob:

Yechim

Har ustunda kamida bitta 1 bo'lsa → 1:

text
  100
| 001
  ───
  101

101 = 4 + 0 + 1 = 5.

2-mashq (o'rta): Manfiy son

−3 ni 8 bitli two's complement ko'rinishida yozing.

Javob:

Yechim
  1. 3 ni 8 bitda yozamiz: 00000011.
  2. Teskari qilamiz: 11111100.
  3. 1 qo'shamiz: 11111101.

Tekshiramiz: −128 + 64 + 32 + 16 + 8 + 4 + 0 + 1 = −128 + 125 = −3. To'g'ri.

3-mashq (qiyin): Uch vaziyat

  1. O'yinda qahramon oltinlari 8 bitli ishorasiz qutida saqlanadi. Hozir 200 ta oltin bor. U yana 100 ta topdi. Qutida nechta oltin qoladi?
  2. Do'konda 0.10 dollarlik 3 ta mahsulot sotib olindi. Bu summani sentda qanday saqlash kerak? Ekranga qanday chiqariladi?
  3. Foydalanuvchining ruxsati 5 (101). U faylga yoza oladimi? (Yozish = 2.)
Yechim
  1. 200 + 100 = 300. 8 bitga ko'pi bilan 255 sig'adi, toshish bo'ladi: 300 − 256 = 44 ta. Qahramon oltin topib, boyish o'rniga kambag'allashdi!
  2. 0.10 dollar = 10 sent. 3 × 10 = 30 sent — butun son, xato yo'q. Ekranga 30 ÷ 100 = 0.30 dollar deb chiqariladi.
  3. AND bilan tekshiramiz: 101 & 010 = 000 = 0. Natija 0 — yoza olmaydi. 5 = 4 + 1, ya'ni faqat o'qish va bajarish.

9. Real ishda

  • Pul bilan ishlash. To'lov tizimlari (Payme, Click, Stripe) bilan ishlaganda summani qaysi birlikda (so'm yoki tiyin) yuborish kerakligini hujjatdan albatta tekshirasiz. Bu yerdagi xato — haqiqiy pul yo'qotishi.
  • Ma'lumotlar bazasi. Jadval ustuni uchun son turini tanlaysiz: 32 bitli (integer) yoki 64 bitli (bigint). Tez o'sadigan ID uchun kichik tur tanlash — kelajakdagi toshish.
  • Ruxsatlar va sozlamalar. Linux ruxsatlari, ba'zi kutubxonalardagi sozlamalar bit bayroqlari bilan yoziladi. Ularni | bilan birlashtirib, & bilan tekshirasiz.
  • Intervyu klassikasi: "Nega JavaScript'da 0.1 + 0.2 !== 0.3?" Endi siz javob bera olasiz: 0.1 ikkilikda cheksiz kasr, cheklangan bitlarda yaxlitlanadi.

Xulosa

  • Kompyuter har bir songa cheklangan joy (8, 16, 32, 64 bit) ajratadi. Sig'magan son toshadi (overflow).
  • Manfiy son: bitlarni teskari qilib, 1 qo'shiladi (two's complement). Eng chap bit — ishora.
  • 8 bitli ishorali son −128 dan 127 gacha, ishorasiz son 0 dan 255 gacha bo'ladi.
  • Kasr sonlar (IEEE 754 float) yaxlitlanadi, shuning uchun 0.1 + 0.2 aniq 0.3 emas.
  • Pulni eng kichik birlikda (tiyin, sent) butun son sifatida saqlang.
  • Bitli amallar: AND (&) tekshiradi, OR (|) birlashtiradi, XOR (^) farqni topadi, surish 2 ga ko'paytiradi yoki bo'ladi.

Keyingi dars: Matn kodlash: ASCII, Unicode va UTF-8 — kompyuter harflar, o'zbekcha o' va emojilarni qanday qilib sonlarga aylantirib saqlashini ko'ramiz.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Sonlar ichkarida: manfiy sonlar, kasr sonlar va bitli amallar — IlmHamroh