3-bo‘lim

Manfiy sonlar va to'ldiruvchi kod

Nima uchun sodda "ishora biti" ishlamaydi, to'ldiruvchi kod qanday qurilgan, chegaradan oshish va nima uchun -128 bor, +128 yo'q.

🕑 9 daqiqa o‘qish 📄 1 176 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Sodda yechim va uning muammosi
  2. To'ldiruvchi kod
  3. Chegaralar va aylanib ketish
  4. Ishorali va ishorasiz
  5. Xulosa

Ikkilik yozuvda minus belgisi yo'q - faqat nollar va birlar. Manfiy sonni qanday yozish kerak?

Javob birinchi qarashda aniq ko'rinadi, lekin u noto'g'ri chiqadi.

Sodda yechim va uning muammosi #

Eng tabiiy g'oya: eng chap bitni ishora uchun ajratamiz.

Eng tabiiy fikr - eng chap bitni ishora uchun ajratish. Bu usul ishora va kattalik deb ataladi:

SonBitlari
+500000101
−510000101
+12701111111
−12711111111

Oddiy ko'rinadi, lekin ikkita jiddiy muammosi bor.

1-muammo: nolning ikki ko'rinishi bor.

SonBitlari
+000000000
−010000000

Bitlari har xil, qiymati esa bir xil - nol. Demak "ikki son tengmi?" degan oddiy tekshiruv ham murakkablashadi.

2-muammo: qo'shish oddiy ishlamaydi.

5 va −5 ni qo'shsak, nol chiqishi kerak edi:

Natija
  00000101      (+5)
+ 10000101      (-5)
= 10001010      (-10 ?)

Natija 10001010 - ya'ni bu usulda -10 degani. Nol emas.

Demak protsessorga qo'shish sxemasidan tashqari alohida ayirish sxemasi kerak bo'lardi. Bu esa qimmat.

Ikkita jiddiy muammo:

  1. Ikkita nol - +0 va -0. Taqqoslash murakkablashadi.
  2. Qo'shish buziladi - 5 + (-5) nol bermaydi.

Ikkinchisi hal qiluvchi. Protsessorga ayirish uchun alohida sxema kerak bo'lardi - qo'shimcha tranzistorlar, qo'shimcha murakkablik.

To'ldiruvchi kod #

Amaldagi yechim boshqacha va u ajoyib darajada nafis. To'ldiruvchi kod (two's complement) deb ataladi.

Qoida: manfiy son uchun barcha bitlarni teskari qiling va bittani qo'shing.

8 bitli to'ldiruvchi kod - doira bo'ylab 0 00000000 127 01111111 -128 10000000 -1 11111111 musbat manfiy 127 + 1 = -128 doira bo'ylab aylanib ketadi bu - toshish (overflow)
Soat siferblati kabi: eng kattadan keyin eng kichigi keladi
SonBitlariO'n oltilikda
5000001010x05
1000000010x01
0000000000x00
−1111111110xFF
−2111111100xFE
−5111110110xFB
127011111110x7F
−128100000000x80

Manfiy sonni qo'lda yasash uchun ikki qadam yetarli. Masalan −5:

QadamNatija
1. 5 ning bitlarini yozamiz00000101
2. Hamma bitni teskarilaymiz11111010
3. Bittani qo'shamiz11111011

Chiqqan 11111011 - aynan jadvaldagi −5.

Endi eng muhim foydasi. 12 + (−5) ni oddiy qo'shish bilan hisoblaymiz:

Natija
   00001100      (12)
 + 11111011      (-5)
 = 100000111     (9 bit chiqdi)

Natija sakkiz bitga sig'madi - to'qqizinchi bit paydo bo'ldi. Uni shunchaki tashlab yuboramiz:

00000111 = 7. To'g'ri javob.

Ya'ni ayirish uchun alohida sxema kerak emas - qo'shish sxemasining o'zi yetarli. 8-bo'limda buni temirda ko'ramiz.

Butun g'oyaning mohiyati

To'ldiruvchi kodda manfiy son shunday tanlanadiki, a + (-a) qo'shilganda natija noldan oshib, aylanib qaytadi.

Soat strelkasiga o'xshatish qulay: 12 soatlik siferblatda "3 soat orqaga" va "9 soat oldinga" bir xil natija beradi.

Aynan shuning uchun:

FoydaIzoh
Ayirish sxemasi kerak emasa - b = a + (-b)
Nol bitta00000000 - yagona ko'rinish
Taqqoslash oddiyBitlarni solishtirish yetarli

Bitta sumator bilan qo'shish ham, ayirish ham bajariladi - bu 8-bo'limda o'zimiz quradigan sxemadir.

-1 ning bitlari hammasi bir bo'lishiga e'tibor bering: 11111111. Bu juda ko'p uchraydigan naqsh - xotira dampida FF FF FF FF ko'rsangiz, bu ko'pincha -1.

Chegaralar va aylanib ketish #

8 bitli ishorali son quyidagi chegaralarda yashaydi:

Qiymat
Eng kichik−128
Eng katta127
Jami qiymatlar256

Manfiylar bittaga ko'p, chunki nol musbat tomonda turadi.

Chegaradan oshib ketsa, son aylanib ketadi:

Kutilgan qiymatHaqiqiy natija
126126
127127chegara
128−128aylanib ketdi
129−127aylanib ketdi
255−1aylanib ketdi
2560aylanib ketdi

Xuddi shu narsa 32 bitda ham sodir bo'ladi - va bu haqiqiy dasturlarda uchraydigan holat:

AmalNatija
Eng katta 32 bitli son2 147 483 647
Unga 1 qo'shsak−2 147 483 648
-128 bor, +128 yo'q

Diqqat qiling: 8 bitda -128 dan 127 gacha. Manfiy tomonda bitta ko'p qiymat bor.

Sabab: nol musbat tomonda hisoblanadi, ya'ni musbatlar uchun 0...127 (128 ta qiymat), manfiylar uchun -128...-1 (yana 128 ta).

Bundan bitta kutilmagan oqibat chiqadi: -128 ning modulini olib bo'lmaydi. Uni musbatga o'girmoqchi bo'lsangiz, yana -128 chiqadi - chunki +128 bu turda mavjud emas.

Bu C va Java da haqiqiy xatolar manbai bo'lgan. 32 bitda ham xuddi shu holat takrorlanadi: eng kichik sonning moduli manfiy qoladi.

Chegaradan oshish - jiddiy zaiflik manbai

Aksariyat tizim dasturlarida butun sonlar qat'iy o'lchamda bo'ladi - ya'ni 8, 16, 32 yoki 64 bit.

Klassik xato shunday ko'rinadi: dastur foydalanuvchidan uzunlik qiymatini oladi va unga 1 qo'shib, shuncha joy ajratmoqchi bo'ladi.

Foydalanuvchi eng katta sonni bersa, +1 dan keyin natija manfiy bo'lib qoladi. Endi dastur manfiy hajmli joy so'raydi - va bu yerdan hamma narsa buziladi.

Bunday xatolar tarixda katta zaifliklarga olib kelgan.

Himoya usullari:

UsulIzoh
Oldindan tekshirishif a > CHEGARA - b
Xavfsiz funksiyalarRust dagi checked_add
Kengroq turint64 ga o'tish
Kompilyator tekshiruvi-ftrapv, sanitizatorlar

Ariane 5 raketasining 1996-yildagi qulashi ham shunga o'xshash turlar o'rtasidagi xato tufayli bo'lgan edi: 64 bitli haqiqiy son 16 bitli butun songa sig'magan.

Ishorali va ishorasiz #

Xuddi bir xil bitlar ikki xil o'qilishi mumkin:

BitlarIshorasizIshorali
0000000000
01111111127127
10000000128-128
11111111255-1

Bitlarning o'zida "men manfiyman" degan ma'lumot yo'q. Uni qanday o'qish - turga bog'liq.

Aynan shuning uchun C da unsigned va signed turlarni aralashtirish xavfli: bir xil baytlar butunlay boshqa son bo'lib chiqadi.

Amaliy topshiriq
  1. -7 ni 8 bitli to'ldiruvchi kodda qo'lda yozing.
  2. Ikki qadamni (teskarilash va +1) yozib ko'rsating.
  3. -1 ning bitlari nima uchun hammasi bir ekanini tushuntiring.
  4. 20 + (-30) ni to'ldiruvchi kodda qo'lda hisoblang.
  5. 12 - 5 ni 12 + (-5) ko'rinishida bajarib, natijani tekshiring.
  6. 4 bitli sonda diapazon qanday bo'lardi? Jadval tuzing.
  7. 4 bitda 7 + 1 nima beradi?
  8. Ishora va kattalik usulining ikki muammosini yoddan sanang.
  9. -128 ning modulini olib bo'lmasligini tushuntiring.
  10. Sevimli tilingizda butun son chegarasidan oshsa nima bo'lishini tekshiring.

Xulosa #

  • Ikkilik yozuvda minus belgisi yo'q - manfiylikni bitlar ifodalashi kerak.
  • Sodda "ishora biti" usuli ikkita muammo beradi: ikkita nol va buzilgan qo'shish.
  • To'ldiruvchi kod: bitlarni teskari qilib, bittani qo'shish.
  • Uning asosiy foydasi - ayirish uchun alohida sxema kerak emas.
  • a - b shunchaki a + (-b) ga aylanadi.
  • -1 ning bitlari hammasi bir: 11111111 (0xFF).
  • 8 bitda diapazon -128...127: manfiylar bittaga ko'p, chunki nol musbat tomonda.
  • Shuning uchun -128 ning moduli qat'iy o'lchamli turda yana -128 bo'ladi.
  • Chegaradan oshish (overflow) jimgina sodir bo'ladi va jiddiy zaiflik manbai.
  • Bir xil bitlar ishorali va ishorasiz turda butunlay boshqa son beradi.

Keyingi bo'limda bitlarni bevosita boshqarishni o'rganamiz: AND, OR, XOR va surish amallari.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.