WisarWisar
Dasturlash kitobi/0-QISM — Tayyorgarlik25 daqiqa

0.1-bob: Kompyuter qanday ishlaydi — CPU, RAM, disk, binary va ma'lumot saqlash

0-QISM — TAYYORGARLIK · 1-mavzu


1. Kirish va motivatsiya

Siz yozadigan har bir kod qatori — let x = 5 bo'ladimi, array.map(...) bo'ladimi yoki butun bir React ilovasi bo'ladimi — oxir-oqibat temir parchasida (kompyuterda) ishlaydi. Dasturchining ishi, aslida, mashinaga nima qilishni aytishdir. Mashinani tushunmasdan unga buyruq berish — chet tilini bilmasdan o'sha tilda she'r yozishga urinishga o'xshaydi: ba'zida tasodifan ishlaydi, lekin nega ishlaganini yoki nega buzilganini hech qachon bilmaysiz.

Ko'p odam dasturlashni "sintaksisni yodlash" deb o'ylaydi. Bu xato. Yaxshi dasturchi bilan o'rtacha dasturchini ajratadigan narsa — ular kompyuterning ichida nima sodir bo'layotganini tasavvur qila olishidir. Mana shu bob aynan o'sha tasavvurning poydevorini quradi.

Bu bobni o'qib bo'lgach, quyidagi savollarga ishonch bilan javob bera olasiz:

  • Kompyuter aslida faqat 0 va 1 bilan ishlasa, qanday qilib matn, rasm, video saqlaydi?
  • let user = { name: "Ali" } deb yozsam, bu qayerda turadi — RAM'dami, diskdami? Ikkalasining farqi nima?
  • Nega dasturim ba'zida "sekin" ishlaydi yoki "xotira yetmadi" deydi?
  • 0.1 + 0.2 nega aniq 0.3 chiqmaydi? (Ha, bu kompyuter haqidagi savol, JavaScript haqida emas.)

Bu — butun kitobning poydevori. Keyinchalik event loop, xotira oqishi (memory leak), Big-O murakkabligi, ma'lumotlar bazasi indekslari, Buffer, performance optimizatsiya — hammasi shu yerda qo'yiladigan tushunchalarga tayanadi.


2. Nazariya — chuqur tushuntirish

2.1. Kompyuter aslida nima?

Eng sodda ta'rifda, kompyuter — ma'lumotni qabul qilib (input), uni qayta ishlab (process), natija chiqaradigan (output) mashina. Hammasi shu uch bosqichdan iborat:

text
   INPUT            PROCESS              OUTPUT
 ┌────────┐      ┌────────────┐      ┌──────────┐
 │ klaviatura│──▶│  CPU + RAM  │────▶│  ekran    │
 │ sichqoncha│   │ (hisoblash) │     │  printer  │
 │ tarmoq    │   └────────────┘     │  tarmoq   │
 └────────┘            │             └──────────┘
                       ▼
                 ┌──────────┐
                 │   DISK    │  (uzoq muddatli saqlash)
                 └──────────┘

Kalkulyator ham, telefon ham, server ham — barchasi shu sxema bo'yicha ishlaydi. Faqat tezligi, hajmi va murakkabligi farq qiladi.

2.2. Nega aynan 0 va 1? (Binary — ikkilik sanoq sistemasi)

Kompyuterning "miyasi" millionlab (zamonaviylarda milliardlab) mayda elektron kalitlardan — tranzistorlardan iborat. Tranzistor — bu juda kichik elektr kalit. Uning faqat ikkita ishonchli holati bor:

  • tok bor biz buni 1 deymiz (yoniq);
  • tok yo'q biz buni 0 deymiz (o'chiq).

O'xshatish: xonangizdagi chiroq kalitini tasavvur qiling. U yo yoniq, yo o'chiq. "Yarim yoniq" degan ishonchli holat yo'q — agar bo'lsa ham, uni aniq o'lchash qiyin. Tranzistor ham xuddi shunday: ikki holat orasini farqlash oson va ishonchli, shuning uchun kompyuter butun dunyoni shu ikki holat bilan ifodalaydi.

Nega 10 ta holat (bizning odatdagi sanoq sistemamizdek) emas? Chunki elektr signalida 10 ta turli kuchlanish darajasini bir-biridan ishonchli ajratish juda qiyin — ozgina shovqin (noise) bo'lsa, 7 ni 6 deb o'qib qo'yish mumkin. Ikkita holatni ("bor/yo'q") ajratish esa nihoyatda ishonchli. Mana shu ishonchlilik uchun kompyuterlar ikkilik sistemada ishlaydi.

Bitta 0 yoki 1 — bu bit (binary digit) deyiladi. Bu axborotning eng kichik bo'lagi.

2.3. Bit, bayt va o'lchov birliklari

Bitta bit juda kam ma'lumot beradi — atigi "ha yoki yo'q". Shuning uchun bitlar guruhlanadi. 8 ta bit birlashsa — bir bayt (byte) hosil bo'ladi.

Nega aynan 8? 8 bit bilan $2^8 = 256$ xil turli kombinatsiya yasash mumkin (00000000 dan 11111111 gacha). 256 ta belgi — lotin alifbosi, raqamlar, tinish belgilari uchun (dastlabki davrda) yetarli edi. Shuning uchun bayt — ma'lumotning amaliy asosiy birligi bo'lib qoldi.

text
1 bit   = 0 yoki 1
1 bayt  = 8 bit         256 xil qiymat (2^8)
2 bayt  = 16 bit        65 536 xil qiymat (2^16)
4 bayt  = 32 bit        ~4.3 milliard qiymat (2^32)
8 bayt  = 64 bit        juda katta (2^64)

Kattaroq birliklar (diqqat — bu yerda eng ko'p uchraydigan chalkashlik bor):

Birlik To'liq nomi Necha bayt Izoh
KB kilobyte 1000 bayt marketingda (disk hajmi)
KiB kibibyte 1024 bayt aniq texnik o'lchov ($2^{10}$)
MB megabyte 1000 KB
MiB mebibyte 1024 KiB
GB gigabyte 1000 MB
GiB gibibyte 1024 MiB

Sababi: kompyuter 2 ning darajalari bilan ishlaydi, ya'ni $2^{10} = 1024$ tabiiy "yumaloq son". Lekin disk ishlab chiqaruvchilar marketingda 1000 ni ishlatadi (shuning uchun "500 GB" disk operatsion tizimda "465 GiB" bo'lib ko'rinadi). Ikkalasi har xil — buni bilish kerak.

2.4. Sanoq sistemalari: decimal, binary, hexadecimal

Biz odamlar o'nlik (decimal) sistemada o'ylaymiz — 10 ta raqam: 0–9. Buning sababi oddiy: qo'limizda 10 ta barmoq bor. Lekin bu — tabiat qonuni emas, balki shartli kelishuv. Boshqa asosli (base) sistemalar ham xuddi shunday ishlaydi.

Asosiy g'oya: har bir raqamning "og'irligi" (razryadi) asos darajalariga teng.

O'nlik sistemada 347 soni aslida:

text
347 = 3×10²  + 4×10¹  + 7×10⁰
    = 3×100  + 4×10   + 7×1
    = 300    + 40     + 7

Ikkilik (binary, asos = 2) sistemada 1011 soni:

text
1011 = 1×2³ + 0×2² + 1×2¹ + 1×2⁰
     = 1×8  + 0×4  + 1×2  + 1×1
     = 8    + 0    + 2    + 1   = 11 (o'nlikda)

O'n oltilik (hexadecimal, asos = 16) sistema dasturlashda juda ko'p uchraydi (ranglar #FF5733, xotira manzillari 0x7ffe, baytlar). Unda 16 ta "raqam" bor: 0–9 va keyin A=10, B=11, C=12, D=13, E=14, F=15.

Nega hex qulay? Chunki bitta hex raqami aynan 4 bitga teng ($16 = 2^4$). Demak 1 bayt (8 bit) = aniq 2 ta hex raqami. Bu uzun binary qatorlarni qisqa va o'qishga oson qiladi:

text
Binary:  1111 0101   (8 bit, o'qish qiyin)
Hex:     F    5        0xF5
Decimal: 245

O'xshatish: binary — bu "1 va 0 lardan iborat juda uzun lenta". Hex esa o'sha lentani 4 talab guruhga bo'lib, har guruhga qisqa nom berish — xuddi telefon raqamini 99 123 45 67 deb bo'lib o'qiganingizdek, esda saqlash osonroq.

2.5. Ma'lumot qanday saqlanadi? (matn, son, rasm)

Kompyuter faqat 0 va 1 ni biladi. Unda matn, rasm, musiqa qayerdan keladi? Javob: hammasi shartli kelishuvlar (encoding — kodlash) orqali sonlarga aylantiriladi.

Matn (text): Har bir harfga bir son biriktiriladi. Eski standart — ASCII: masalan A = 65, B = 66, a = 97, 0 (raqam belgisi) = 48. Bu son esa baytda binary ko'rinishida saqlanadi:

text
'A'    65    01000001  (1 bayt)

ASCII faqat 128 ta belgini qamragan — o'zbek , , emoji , xitoy ieroglifi unga sig'magan. Shuning uchun zamonaviy standart — Unicode, va uning eng mashhur kodlash usuli — UTF-8. UTF-8 da oddiy lotin harfi 1 bayt, / kabi belgilar 2 bayt, emoji esa 4 baytgacha joy egallaydi. (Buni 0.4-bob va keyinchalik Buffer mavzusida yana ko'ramiz.)

Sonlar: butun sonlar (integer) to'g'ridan-to'g'ri binary'da saqlanadi. Kasr sonlar (3.14) esa floating point (suzuvchi nuqta) standarti (IEEE 754) bo'yicha saqlanadi — bu juda muhim, chunki aynan shu narsa 0.1 + 0.2 !== 0.3 muammosini keltirib chiqaradi (6-bo'limda batafsil).

Rasm: rasm — bu mayda nuqtalar (piksel) to'plami. Har bir pikselning rangi 3 ta son bilan beriladi: qizil (R), yashil (G), ko'k (B), har biri 0–255 oralig'ida (ya'ni 1 bayt). Demak bitta piksel ≈ 3 bayt. 1920×1080 rasm ≈ $1920 \times 1080 \times 3 ≈ 6.2$ MB (siqilmagan holda). Mana shuning uchun rasmlar JPEG, PNG formatlarida siqiladi (compression).

Asosiy xulosa: kompyuterda hamma narsa — son. Son esa — binary. Farqi faqat shundaki, biz o'sha sonni qaysi "kelishuv" bilan o'qiymiz. Aynan bitta bayt 01000001 — agar uni ASCII deb o'qisangiz 'A', agar son deb o'qisangiz 65, agar rang deb o'qisangiz 65 darajadagi qizillik. Ma'no — kontekstdan (talqindan) kelib chiqadi.

2.6. CPU — kompyuterning miyasi

CPU (Central Processing Unit — markaziy protsessor) — bu hisob-kitoblarni va buyruqlarni bajaradigan qism. U juda sodda ishlarni, lekin dahshatli tez bajaradi.

CPU ichidagi asosiy qismlar:

  • ALU (Arithmetic Logic Unit) — arifmetik (qo'shish, ayirish) va mantiqiy (AND, OR, taqqoslash) amallarni bajaradi.
  • Control Unit (boshqaruv bloki) — qaysi buyruq keyin bajarilishini boshqaradi.
  • Registrlar — CPU ichidagi nihoyatda kichik va nihoyatda tez xotira hujayralari. Hozir ishlatilayotgan sonlar shu yerda turadi.
  • Clock (soat) — CPU ritmini belgilaydi. "3 GHz protsessor" degani — sekundiga 3 milliard marta "taq" etadi, va har "taq"da bir (yoki bir nechta) sodda amal bajarilishi mumkin.

CPU har doim bitta sodda tsiklni takrorlaydi — fetch–decode–execute (olib kel – tushun – bajar):

text
        ┌──────────────────────────────────┐
        ▼                                   │
   1. FETCH      RAM'dan keyingi buyruqni olib keladi
        │
        ▼
   2. DECODE     bu qanday buyruq ekanini tushunadi
        │            (qo'shishmi? xotiradan o'qishmi?)
        ▼
   3. EXECUTE    buyruqni bajaradi (masalan ALU qo'shadi)
        │
        └──────────────────────────────────┘
              (va yana boshidan, milliard marta/sek)

Core (yadro) — bu aslida bitta to'liq CPU. "4 yadroli protsessor" degani — 4 ta ish bir vaqtda, haqiqatan parallel bajarilishi mumkin. Thread (oqim) — bu bajarilayotgan ishlar ketma-ketligi; bitta yadro ko'plab thread'larni juda tez navbatma-navbat (almashtirib) bajarib, go'yo bir vaqtda bo'layotgandek ko'rsatishi mumkin.

DIQQAT: JavaScript/Node.js asosan bitta threadda ishlaydi. Mana shuning uchun "event loop", "asinxron kod", "non-blocking" tushunchalari shunchalik muhim — biz 2.11 va 5.1 boblarda bunga chuqur kiramiz. Hozir shuni eslab qoling: bitta oshpaz (thread) bir vaqtda ko'p taom tayyorlayotgandek ko'rinishi, lekin aslida ularni tez almashtirib turishi mumkin.

2.7. RAM — qisqa muddatli, tez xotira

RAM (Random Access Memory — tezkor xotira) — dastur ishlayotgan paytda ma'lumotlarini saqlaydigan joy. Uning ikki muhim xususiyati bor:

  1. Tez — CPU undan ma'lumotni juda tez oladi (diskdan ancha tez).
  2. Vaqtinchalik (volatile) — tok o'chsa, hamma narsa o'chib ketadi. Shuning uchun yozayotgan hujjatingizni saqlamasdan kompyuter o'chsa, yo'qoladi — chunki u faqat RAM'da turardi.

RAM'ni juda katta kataklar (hujayralar) qatori deb tasavvur qiling. Har bir katakning manzili (address) bor (0, 1, 2, 3, ...) va har biriga bitta bayt sig'adi:

text
manzil:   0      1      2      3      4      5    ...
        ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐
RAM:    │ 72 │ │ 65 │ │ 76 │ │ 76 │ │ 79 │ │ .. │
        └────┘ └────┘ └────┘ └────┘ └────┘ └────┘
          'H'    'A'    'L'    'L'    'O'

"Random access" degani — CPU istalgan manzilga bevosita, bir xil tezlikda murojaat qila oladi (kitobning istalgan sahifasini darrov ochgandek). Bu — keyin ko'radigan "ketma-ket o'qish" (masalan eski magnit lenta) ning aksi.

Dastur ishga tushganda, uning kodi va ma'lumotlari diskdan RAM'ga yuklanadi, chunki CPU faqat RAM (va undan ham tezroq registr/cache) bilan to'g'ridan-to'g'ri ishlaydi. let user = {...} deb yozganingizda, o'sha obyekt — RAM'ning bir bo'lagida yashaydi.

2.8. Disk — uzoq muddatli, doimiy xotira

Disk (HDD yoki SSD) — ma'lumotni doimiy saqlaydi. Tok o'chsa ham yo'qolmaydi (non-volatile). Fayllaringiz, suratlaringiz, operatsion tizim — hammasi shu yerda.

  • HDD (Hard Disk Drive) — aylanadigan magnit disk. Arzon, hajmi katta, lekin sekin (mexanik harakat bor).
  • SSD (Solid State Drive) — mexanik qismsiz, flesh-xotira. Qimmatroq, lekin HDD'dan o'nlab-yuzlab marta tez.

Disk RAM'dan ancha sekin, lekin ancha arzon va doimiy. Mana shu "tez lekin vaqtinchalik" (RAM) va "sekin lekin doimiy" (disk) o'rtasidagi savdo (trade-off) — butun kompyuter dizaynining markazida turadi.

2.9. Xotira ierarxiyasi (memory hierarchy) — eng muhim tushuncha

Bu bo'limning eng qimmatli g'oyasi shu. Kompyuterda xotira bir nechta darajada joylashgan — yuqoriga chiqqan sari tezroq, kichikroq, qimmatroq:

text
       TEZLIK ▲                                  HAJM
              │   ┌───────────────┐
   eng tez    │   │   Registrlar   │  ~1 KB     eng kichik
              │   ├───────────────┤
              │   │   L1 / L2 / L3  │  bir necha MB
              │   │     Cache       │
              │   ├───────────────┤
              │   │      RAM        │  8–64 GB
              │   ├───────────────┤
              │   │   SSD / Disk    │  256 GB – bir necha TB
   eng sekin  │   ├───────────────┤
              ▼   │  Tarmoq/Cloud   │  ~cheksiz   eng katta
                  └───────────────┘

Tezlik farqi shunchalik kattaki, uni "inson o'lchovida" tasvirlash kerak. Agar registrdan ma'lumot olishni 1 sekund deb olsak (taxminiy nisbatlar):

Qayerdan Inson o'lchovida (taxminan)
Registr / L1 cache 1 sekund
RAM bir necha daqiqa
SSD bir necha kun
HDD bir necha oy
Tarmoq (boshqa shahar serveri) bir necha yil

Mana shuning uchun caching (tez-tez kerak bo'ladigan ma'lumotni tezroq joyga ko'chirib qo'yish) — dasturlashda hamma joyda uchraydi: CPU cache, Redis (5.21-bob), brauzer cache, Next.js cache (13.7-bob). Hammasining sababi — bitta: pastdagi sekin qatlamga kamroq murojaat qilish.

Cache aynan nega ishlaydi? U ikkita kuzatishga — lokallik (locality) tamoyiliga — tayanadi:

  • Vaqtinchalik lokallik (temporal locality): hozir ishlatilgan ma'lumot tez orada yana kerak bo'lish ehtimoli yuqori (masalan, tsikldagi hisoblagich yoki tez-tez chaqiriladigan funksiya).
  • Fazoviy lokallik (spatial locality): bir manzildagi ma'lumot kerak bo'lsa, uning yonidagi manzillar ham tez orada kerak bo'ladi (masalan, massiv elementlari xotirada ketma-ket joylashadi).

Shuning uchun CPU RAM'dan bittagina bayt emas, balki butun cache line (odatda 64 bayt) ni birato'la o'qiydi. Massivni tartib bilan aylanib chiqish (arr[0], arr[1], arr[2]...) cache uchun ideal: birinchi elementni o'qiganda, qo'shnilari ham allaqachon cache'ga tushgan bo'ladi. Mana shuning uchun massiv (ketma-ket xotira) ko'pincha bog'langan ro'yxatdan (linked list — xotirada tarqoq joylashgan) tezroq ishlaydi — garchi ikkalasida ham "bitta elementga murojaat" nazariy jihatdan bir xil ko'rinsa-da (buni 3-QISMda Big-O bilan birga ko'ramiz). Aksincha, kerakli ma'lumot cache'da topilmasa — bu cache miss deyiladi va CPU sekin RAM'ga borishga majbur bo'ladi (o'nlab marta sekinroq).

Amaliy xulosa: ikki algoritmning Big-O murakkabligi bir xil bo'lsa ham, xotirani ketma-ket (cache-friendly) ishlatadigani amalda bir necha barobar tez bo'lishi mumkin. "Mechanical sympathy" — temir qanday ishlashini hisobga olib kod yozish — senior dasturchining kuchli quroli.

Hayotiy o'xshatish — oshpaz:

  • Registr/cache = oshpazning qo'lidagi narsalar (darrov ishlatadi).
  • RAM = ish stoli ustidagi masalliqlar (bir necha qadam narida).
  • Disk = omborxona (borib kelish kerak, sekin).
  • Tarmoq = bozorga borib kelish (juda uzoq).

Yaxshi oshpaz eng ko'p kerak bo'ladigan narsalarni qo'li ostiga qo'yadi. Yaxshi dasturchi ham xuddi shunday — ma'lumotni qancha tez-tez kerak bo'lsa, shuncha "yuqori"da saqlaydi.

2.10. Manfiy sonlar va bitli amallar (two's complement, bitwise)

Yuqorida faqat musbat sonlarni ko'rdik. Lekin -5 kabi manfiy son binary'da qanday saqlanadi? "Minus belgisi" uchun alohida joy yo'q — xotirada faqat 0 va 1 bor. Yechim — ikkilik to'ldiruvchi (two's complement) usuli; deyarli barcha zamonaviy protsessorlar aynan shuni ishlatadi.

G'oya: eng chapdagi (eng katta razryadli) bit ishora biti (sign bit) vazifasini bajaradi. Sonni manfiyga aylantirish uchun: barcha bitlarni teskari qiling (NOT), so'ng natijaga 1 qo'shing. 8-bitli misol:

text
  +5  =  00000101
  teskari (NOT)  =  11111010
  +1             =  11111011     bu -5

  8-bitli son qamrovi:
    ishorasiz (unsigned):  0 ... 255        (00000000 ... 11111111)
    ishorali (signed):  -128 ... +127       (eng chap bit = ishora)

Bu usul nega chiroyli? Chunki qo'shish va ayirish bitta sxema bilan ishlaydi. 5 + (-5) ni hisoblang: 00000101 + 11111011 = 1 00000000. 8 bitdan oshib ketgan bit ("carry") tashlab yuboriladi va natija 00000000 = 0 bo'ladi — to'g'ri! CPU ayirishni alohida o'rganishi shart emas: manfiy sonni qo'shish kifoya.

Endi bitli amallar (bitwise) — "hamma narsa son" g'oyasining bevosita davomi. Sonni bitlar to'plami deb qarab, ular ustida bevosita amal bajariladi:

Amal Nomi Ma'nosi
& AND ikkala bit ham 1 bo'lsa 1
| OR bittasi 1 bo'lsa 1
^ XOR bitlar farq qilsa 1
~ NOT har bitni teskari qiladi
<< chapga surish x << 1 = x ni 2 ga ko'paytirish
>> o'ngga surish x >> 1 = x ni 2 ga bo'lish (butun qism)

Bular nega kerak: ruxsat/bayroqlarni (flags) bitta songa joylash, rang kanallari (RGBA), nihoyatda tez ko'paytirish/bo'lish, xeshlash va past darajali optimizatsiya. Amalda buni 4-bo'lim, Misol 6 da ko'rasiz.

DIQQAT (endianness): ko'p baytli son xotirada qaysi tartibda saqlanadi? Little-endian (eng kichik bayt oldin — x86, ARM) yoki big-endian (eng katta bayt oldin — tarmoq protokollari, "network byte order"). Bu farq Buffer va binary fayl/protokol bilan ishlaganda muhim (5.4-bob): bir tartibda yozilgan baytni boshqa tartibda o'qisangiz, son buziladi. JavaScriptda esa bitli amallar sonni avtomatik 32-bitli ishorali butun songa keltirib bajaradi — buni quyidagi misolda ko'rasiz.


3. Amaliy belgilash va birliklar (sintaksis)

Bu mavzu "kod sintaksisi" emas, lekin dasturlashda har kuni uchraydigan yozuvlar bor. Ularni o'qiy olish kerak:

text
0b1011       binary (ikkilik) yozuvi. "0b" prefiksi. = 11
0o17         octal (sakkizlik) yozuvi. "0o" prefiksi. = 15
0xFF         hex (o'n oltilik) yozuvi. "0x" prefiksi. = 255
255          decimal (o'nlik), oddiy son

Ranglar (CSS va dizaynda doim hex):

text
#FF0000   R=FF(255) G=00 B=00   to'liq qizil
#00FF00   R=00 G=FF(255) B=00   to'liq yashil
#000000   qora    #FFFFFF  oq

O'lchov birliklarini o'qish:

text
512 MB    o'rtacha rasm/hujjatlar uchun ko'p
8 GB      odatdagi noutbuk RAM
1 TB      odatdagi SSD hajmi
3.2 GHz   CPU chastotasi (sekundiga 3.2 mlrd takt)
100 Mbps  internet tezligi (megabit/sek, bit — bayt emas!)

Diqqat: internet tezligi bitda (Mbps — megabit), fayl hajmi esa baytda (MB — megabayt) o'lchanadi. 8 bit = 1 bayt. Shuning uchun "100 Mbps" internetda fayl taxminan 100 / 8 = 12.5 MB/sek tezlikda yuklanadi. Bu — provayderlar yoqtiradigan "marketing" chalkashligi.


4. Batafsil kod namunalari

Endi nazariyani kodda ko'ramiz. Bu yerda JavaScript ishlatamiz — chunki u sizda bor va keyin shu tilga chuqur kiramiz. Har bir muhim qatorga izoh berilgan. Bu kodlarni Node.js'da (node fayl.js) yoki brauzer konsolida ishlatib ko'rishingiz mumkin.

Misol 1 — Sanoq sistemalari orasida o'tkazish

js
// Bitta son — turli sistemalarda ko'rsatamiz.
const son = 245;

// toString(asos) — sonni boshqa sanoq sistemasidagi MATN ko'rinishiga o'giradi.
console.log(son.toString(2));   // "11110101"   binary (ikkilik)
console.log(son.toString(8));   // "365"        octal (sakkizlik)
console.log(son.toString(16));  // "f5"         hex (o'n oltilik)
console.log(son.toString(10));  // "245"        decimal (odatdagi)

// parseInt(matn, asos) — teskari amal: matnni o'sha asosdagi son deb o'qiydi.
console.log(parseInt("11110101", 2));  // 245   binary matnni songa
console.log(parseInt("f5", 16));       // 245   hex matnni songa

// JS'da sonni to'g'ridan-to'g'ri boshqa sistemada yozish ham mumkin:
console.log(0b11110101); // 245   0b = binary literal
console.log(0o365);      // 245   0o = octal literal
console.log(0xf5);       // 245   0x = hex literal
// Yuqoridagi uchalasi — AYNAN bir xil son. Faqat YOZILISHI har xil.

Misol 2 — Harf qanday songa aylanishi (encoding)

js
const harf = "A";

// charCodeAt(0) — birinchi belgining Unicode (kod) raqamini qaytaradi.
console.log(harf.charCodeAt(0)); // 65   'A' ning kodi

// String.fromCharCode(son) — teskarisi: koddan harf yasaydi.
console.log(String.fromCharCode(66)); // "B"

// "HALLO" so'zidagi har bir harfning kodini ko'ramiz:
for (const ch of "HALLO") {
  // ch — har bir harf; ch.charCodeAt(0) — uning son kodi
  console.log(ch, "->", ch.charCodeAt(0));
}
// H -> 72   A -> 65   L -> 76   L -> 76   O -> 79
// Aynan shu sonlar RAM'da binary holatda saqlanadi.

Misol 3 — Matn necha baytga aylanishini ko'rish (UTF-8)

js
// TextEncoder — matnni UTF-8 baytlar massiviga aylantiradigan brauzer/Node API.
const encoder = new TextEncoder();

const a = encoder.encode("A");        // oddiy lotin harfi
const b = encoder.encode("oʻ");       // o'zbekcha "oʻ"
const c = encoder.encode("");       // emoji

console.log(a.length); // 1   'A' UTF-8'da 1 bayt
console.log(b.length); // 3   'oʻ' (o + maxsus belgi) ko'proq bayt
console.log(c.length); // 4   emoji 4 bayt!

// XULOSA: matnning "uzunligi" (belgilar soni) va uning DISK/RAM'da
// egallaydigan BAYT hajmi — bu IKKI XIL narsa. Til o'zbekcha yoki
// emoji bo'lsa, bayt hajmi belgilar sonidan katta bo'ladi.

Misol 4 — Bir bayt = 8 bit ekanini ko'rsatish

js
// 1 baytga sig'adigan eng katta son: 11111111 (binary) = 255
const engKatta = 0b11111111;
console.log(engKatta);                  // 255

// padStart(8, "0") — chap tomonni 0 bilan to'ldirib, doim 8 xonali qiladi.
// Shunda binary ko'rinishi to'liq 1 bayt (8 bit) bo'lib chiroyli ko'rinadi.
for (let n = 0; n <= 5; n++) {
  console.log(n, "->", n.toString(2).padStart(8, "0"));
}
// 0 -> 00000000
// 1 -> 00000001
// 2 -> 00000010
// 3 -> 00000011
// 4 -> 00000100
// 5 -> 00000101
// Har bir ustun — bitta bit. Eng o'ngdagisi "1 lik", keyingisi "2 lik"...

Misol 5 — Floating point haqiqati (eng mashhur "g'alati" hodisa)

js
// Kasr sonlar binary'da ANIQ saqlanmaydi (xuddi 1/3 ni o'nlikda
// 0.3333... deb cheksiz yozganimizdek, ba'zi kasrlar 2 lik sistemada cheksiz).
console.log(0.1 + 0.2);            // 0.30000000000000004  (!!!)
console.log(0.1 + 0.2 === 0.3);   // false   shuning uchun ===  ishlamaydi

// To'g'ri taqqoslash: ikki son orasidagi farq juda kichik (epsilon) bo'lsa,
// ularni "teng" deb hisoblaymiz.
const teng = Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON;
console.log(teng); // true

// Pul bilan ishlaganda eng xavfsiz yo'l — eng kichik birlikni (tiyin/sent)
// BUTUN son sifatida saqlash. Masalan 19.99 so'mni 1999 tiyin deb saqlash.
const narx = 1999; // tiyinlarda — kasr yo'q, xato yo'q
console.log(narx / 100); // 19.99   faqat ko'rsatishda bo'lamiz

Misol 6 — Bitli amallar (bitwise) amalda

js
// 1) Asosiy bitli amallar (JS ularni 32-bitli butun son sifatida bajaradi).
console.log(5 & 3);   // 1     0101 & 0011 = 0001
console.log(5 | 3);   // 7     0101 | 0011 = 0111
console.log(5 ^ 3);   // 6     0101 ^ 0011 = 0110  (farq qilgan bitlar)
console.log(~5);      // -6    bitlarni teskari (two's complement natijasi!)
console.log(5 << 1);  // 10    chapga surish = ×2
console.log(5 >> 1);  // 2     o'ngga surish = ÷2 (butun qism)

// 2) AMALIY: bir nechta ruxsatni bitta songa joylash (flags / bitmask).
//    Unix fayl ruxsatlari (chmod 755) aynan shu g'oyaga asoslanadi.
const OQISH    = 1; // 001
const YOZISH   = 2; // 010
const BAJARISH = 4; // 100

// Foydalanuvchiga o'qish + yozish beramiz (kerakli bitlarni yoqamiz):
let ruxsat = OQISH | YOZISH;            // 011 = 3
console.log(ruxsat);                    // 3

// "Yozish ruxsati bormi?" — AND bilan bitni tekshiramiz:
console.log((ruxsat & YOZISH) !== 0);   // true
console.log((ruxsat & BAJARISH) !== 0); // false

// Bitta ruxsatni o'chirish (yozishni olib tashlash): & ~FLAG
ruxsat = ruxsat & ~YOZISH;              // 001 = 1
console.log(ruxsat);                    // 1 — faqat o'qish qoldi

// XULOSA: bitta butun son ichida 32 tagacha "ha/yo'q" bayroqni saqlash mumkin —
// bu xotira tejaydi va tekshirish nihoyatda tez (bitta CPU amali).

5. To'g'ri va noto'g'ri holatlar

1) Kasr sonlarni === bilan taqqoslash

js
//  NOTO'G'RI — floating point xatosi tufayli kutilmagan natija
if (0.1 + 0.2 === 0.3) { /* bu blok HECH QACHON ishlamaydi */ }

//  TO'G'RI — epsilon (juda kichik farq) bilan taqqoslash
if (Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON) { /* ishlaydi */ }

Nega: kasr sonlar binary'da yaxlitlanadi; aniq tenglik ishonchsiz.

2) Pulni kasr son sifatida saqlash

js
//  NOTO'G'RI — moliyaviy hisoblarda yaxlitlash xatolari yig'iladi
let balans = 0.0;
for (let i = 0; i < 10; i++) balans += 0.1;
console.log(balans); // 0.9999999999999999 — 1 emas!

//  TO'G'RI — eng kichik birlikni butun songa aylantirib saqlash
let balansTiyin = 0;
for (let i = 0; i < 10; i++) balansTiyin += 10; // 0.1 so'm = 10 tiyin
console.log(balansTiyin / 100); // 1   aniq

3) Birliklarni chalkashtirish (bit vs bayt, KB vs KiB)

js
//  NOTO'G'RI — "100 Mbps internetda 100 MB fayl 1 sekundda yuklanadi"
//    deb o'ylash. Mbps — megaBIT, MB — megaBAYT. 8 barobar farq!

//  TO'G'RI — bitni baytga o'tkazib hisoblash
const tezlikMbps = 100;
const tezlikMBps = tezlikMbps / 8;     // 12.5 MB/sek
const faylMB = 100;
console.log(faylMB / tezlikMBps, "sekund"); // 8 sekund (taxminan)

4) Katta fayllarni butunlay RAM'ga yuklash

js
//  NOTO'G'RI — 5 GB faylni bir varakayiga RAM'ga o'qish
// const data = fs.readFileSync("katta-video.mp4"); // RAM portlaydi!

//  TO'G'RI — stream (oqim) orqali bo'lak-bo'lak o'qish (5.4-bobda chuqur)
// fs.createReadStream("katta-video.mp4").pipe(...);

Nega: RAM cheklangan (masalan 8 GB). 5 GB faylni butunlay yuklash xotirani to'ldiradi va dastur qulaydi. Disk katta, RAM kichik — buni esda tuting.


6. Keng tarqalgan xatolar va yechimlari

Xato 1 — RangeError: Maximum call stack size exceeded

js
function cheksiz() {
  return cheksiz(); // o'zini to'xtovsiz chaqiradi
}
cheksiz();
//  RangeError: Maximum call stack size exceeded

Sababi: har bir funksiya chaqiruvi RAM'dagi maxsus joyni — call stackni — egallaydi. Cheksiz rekursiya stack'ni to'ldiradi va u "toshib ketadi". Yechimi: rekursiyaga to'xtash sharti (base case) qo'yish, yoki tsikl (loop) bilan yozish. (Rekursiyani 3.11-bobda chuqur ko'ramiz.)

Xato 2 — JavaScript heap out of memory

text
FATAL ERROR: Reached heap limit Allocation failed -
JavaScript heap out of memory

Sababi: dastur RAM'da haddan tashqari ko'p ma'lumot yig'di (masalan cheksiz o'sib boruvchi massiv, yoki memory leak). Yechimi: ma'lumotni stream bilan qismlarga bo'lib ishlash; keraksiz havolalarni (reference) tozalash; kerak bo'lsa Node'ga ko'proq xotira berish (node --max-old-space-size=4096).

Xato 3 — butun son chegarasidan oshib ketish (integer overflow / precision)

js
console.log(9007199254740991 + 1); // 9007199254740992  (to'g'ri, oxirgi aniq son)
console.log(9007199254740991 + 2); // 9007199254740992  (XATO! 2 qo'shilmadi)

Sababi: JS oddiy number 64-bitli floating point bo'lib, faqat Number.MAX_SAFE_INTEGER (≈ 9 kvadrilion) gacha butun sonlarni aniq saqlaydi. Yechimi: undan katta butun sonlar uchun BigInt ishlatish:

js
console.log(9007199254740991n + 2n); // 9007199254740993n   aniq (n — BigInt)

Xato 4 — NaN (Not a Number) paydo bo'lishi

js
console.log("salom" * 2);     // NaN
console.log(0 / 0);           // NaN
console.log(parseInt("xyz")); // NaN

Sababi: son bo'lmagan narsa ustida arifmetik amal bajarildi. Yechimi: kirish ma'lumotini ishlatishdan oldin Number.isNaN(x) bilan tekshirish. (Bu — 0.6-bobdagi "kirishni tekshirish" tamoyiliga bog'lanadi.)


7. Integratsiya — bu mavzu stack'ning qayerida uchraydi

Bu fundamental bilim butun kitob davomida qayta-qayta chiqadi. Mana xaritasi:

  • Event loop & async (2.11, 5.1): Node bitta thread'da ishlaydi 2.6-bob — shuning uchun asinxronlik kerak.
  • Buffer & Streams 5.4-bob: baytlar bilan to'g'ridan-to'g'ri ishlash; katta fayllarni RAM'ni to'ldirmasdan o'qish (5-bo'limga qara).
  • Big-O murakkabligi 3.1-bob: algoritm tezligi — aslinda "CPU necha amal bajaradi" va "necha RAM kerak" degani.
  • Ma'lumotlar bazasi indekslari (6.3, 6.9): indeks — bu disk (sekin) o'rniga RAM'da tez qidirish uchun tuzilma. Xotira ierarxiyasining 2.9-bob amaliy ko'rinishi.
  • Caching: Redis 5.21-bob, Next.js cache 13.7-bob: "sekin qatlamga kam murojaat" tamoyili 2.9-bob.
  • Xavfsizlik — parol xeshlash (5.15, 14.3): xesh — baytlar ustidagi matematik amal; binary tushunchasiga tayanadi.
  • Performance 11.11-bob: re-render'larni kamaytirish — aslida CPU ishini kamaytirish.

Boshqacha aytganda: bu bobni yaxshi tushunsangiz, keyingi 150 bob osonroq bo'ladi.


8. Eng yaxshi amaliyotlar (best practices)

  • Hamma narsa — son, son esa kontekstga bog'liq. "Bu bayt nimani anglatadi?" deb so'rashga odatlaning — matnmi, sonmi, ranglarmi?
  • Pul va aniq hisoblarda hech qachon floating point ishlatmang. Eng kichik birlikni butun son (yoki maxsus decimal kutubxona) sifatida saqlang.
  • Xotira cheklangan resurs — uni hurmat qiling. Katta ma'lumotni stream bilan ishlang, keraksiz havolalarni ushlab turmang.
  • "Tez = yuqori qatlam" tamoyilini eslab turing. Tez-tez kerak bo'ladigan ma'lumotni cache'lang; sekin qatlamga (disk, tarmoq) kamroq boring.
  • Birliklarni doim aniqlashtiring. MB mi MiB mi? bit mi bayt mi? Bu — real bug'larning manbai.
  • BigIntni katta butun sonlar uchun biling. ID, vaqt belgisi (timestamp), moliyaviy summalar katta bo'lsa kerak bo'ladi.
  • O'lchamlar haqida "taxminiy his" rivojlantiring. "Bu massivda 1 million obyekt bo'lsa, taxminan necha MB RAM yeydi?" deb chama qila olish — senior dasturchining belgisidir.

9. Amaliy loyiha: "Sanoq Sistemalari va Bayt Kalkulyatori"

Bu mavzuni mustahkamlash uchun kichik, lekin chuqur loyiha. Hech qanday kutubxonasiz, faqat sof JavaScript va Node.js bilan (terminal dasturi) yoki oddiy HTML sahifa sifatida.

Maqsad

Foydalanuvchi son yoki matn kiritganda, uni turli sanoq sistemalarida va bayt ko'rinishida ko'rsatadigan kalkulyator yozish. Maqsad — sonlar va kodlash "ko'rinmas" emas, balki ko'z bilan ko'riladigan bo'lishi.

Talablar (requirements)

  1. Son rejimi: foydalanuvchi o'nlik son kiritsa (masalan 245), dastur uni:
    • binary (11110101),
    • octal (365),
    • hex (f5) ko'rinishida chiqarsin. Binary doim to'liq baytlarga (8, 16, 24 bit...) 0 bilan to'ldirib ko'rsatilsin.
  2. Teskari rejim: foydalanuvchi binary yoki hex kiritsa (masalan 0xFF yoki 0b1011), dastur uni o'nlikka aylantirsin.
  3. Matn rejimi: foydalanuvchi so'z kiritsa (masalan Salom), dastur:
    • har bir harfning Unicode kodini,
    • har bir harfning binary (8-bit) ko'rinishini,
    • butun so'z UTF-8'da necha bayt ekanini chiqarsin.
  4. Bayt hisoblagich: foydalanuvchi 1.5 GB yoki 500 MiB kabi hajm kiritsa, uni baytlarga aylantirsin (KB/KiB farqini to'g'ri hisobga olsin).

Maslahatlar (hint)

  • Number.prototype.toString(asos) va parseInt(matn, asos) — asosiy qurolingiz.
  • padStart(8, "0") bilan binary'ni chiroyli, to'liq baytga to'ldiring.
  • Matn baytlari uchun new TextEncoder().encode(str).length dan foydalaning.
  • Kiritilgan qiymat son ekanini Number.isNaN() bilan tekshiring (6-bo'limni eslang).
  • Terminal versiyasi uchun process.argv (buyruq qatori argumentlari) yoki readline modulidan foydalanishingiz mumkin (buni 0.3 va 5.3-boblarda ko'ramiz — hozir oddiy prompt/o'zgaruvchi ham bo'ladi).
  • KB/KiB: 1 KB = 1000, 1 KiB = 1024. Lug'at (object) tuzib, har birlikka ko'paytuvchini bog'lang.

"Tayyor" mezonlari (acceptance criteria)

  • 245 kiritilganda 11110101, 365, f5 to'g'ri chiqadi.
  • 0xFF kiritilganda 255 chiqadi.
  • Salom kiritilganda har bir harf kodi va qo'shilsa bayt soni to'g'ri o'zgaradi.
  • 1 KiB 1024, 1 KB 1000 to'g'ri farqlanadi.
  • Noto'g'ri kirish ("abc" ni son rejimida) berilganda dastur qulamaydi, balki tushunarli xabar beradi.
  • (Bonus) Natijalar jadval ko'rinishida chiroyli chiqadi.

Yechim kodini bu yerda bermaymiz — buni o'zingiz yozishingiz kerak, chunki haqiqiy o'rganish aynan yozish jarayonida bo'ladi.


10. Xulosa va keyingi bobga ko'prik

Bu bobda kompyuterning eng tubidagi haqiqatlarni o'rgandik:

  • Kompyuter input process output mashinasi; ichida hammasi 0 va 1 (binary) bilan ifodalanadi, chunki tranzistorlar ikki holatli.
  • Bit — eng kichik birlik; 8 bit = 1 bayt. Hex (0x) — baytlarni qisqa yozish usuli.
  • Hamma narsa — son, faqat talqini (encoding) farq qiladi: matn (ASCII/UTF-8), rasm (RGB), kasr son (floating point).
  • Manfiy sonlar ikkilik to'ldiruvchi (two's complement) bilan saqlanadi; bitli amallar (& | ^ ~ << >>) bayroq, ruxsat va past darajali optimizatsiyada ishlatiladi.
  • Cache va lokallik: xotirani ketma-ket (cache-friendly) ishlatish bir xil Big-O da ham kodni amalda tezlashtiradi — massiv vs linked list.
  • CPU — fetch–decode–execute tsiklini milliard marta/sek takrorlaydi; yadro parallel ish, JS esa asosan bitta thread.
  • Xotira ierarxiyasi: registr cache RAM disk tarmoq. Yuqoriga chiqqan sari tez, kichik, qimmat. RAM — tez lekin vaqtinchalik; disk — sekin lekin doimiy.
  • Bu bilimlar floating point xatolari, memory leak, Big-O, indeks, cache kabi keyingi mavzularning poydevori.

Keyingi bob — 0.2-bob: Operatsion tizimlar va fayl tizimi. Endi temirni (hardware) tushundik; navbat — o'sha temirni boshqaradigan va biz har kuni ishlaydigan operatsion tizim (Windows, Linux, macOS) hamda fayllar qanday tashkil etilishiga. Bu — terminal 0.3-bob va Node.js 0.7-bob oldidan zarur ko'prik.

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
0.1-bob: Kompyuter qanday ishlaydi — CPU, RAM, disk, binary va ma'lumot saqlash — Wisar