Побитови операции и представяне на числени данни - УПП, Седмица 14, 15.01.2026
Побитови операции и представяне на числени данни
Какво е бит?
#- всичко в компютъра се представя в двоична бройна система
- бит е най-малката единица памет
- байт (byte) е най-малката адресируема единица памет
- дума (word) е най-голямата обработваема единица памет
Размерите на тези стойности (и някои други ефекти) се определят от архитектурата на процесора:
- На модерни процесори:
x86-64(Intel/AMD),ARM(Apple M series/Snapdragon/Exynos/Cortex)
байт е 8 бита, дума е 64 бита - процесора извършва повечето инструкции върху думи
- в повечето архитектури, размера на един адрес (указател) е една дума
boolзаема един байт, въпреки че стойността му може да се побере в един бит
Общо взето, за модерен процесор/ОС/... може да използвате размерите в долната таблица.
Обаче, стандарта на C++ определя единствено минимален размер за типовете.
Долните стойности не са закон!
| Тип | Размер |
|---|---|
bool, char
| "1" бит (1 байт) |
short
| 16 бита (2 байта) |
int, float
| 32 бита (4 байта) |
long
| 32 бита Windows, 64 бита MacOS/Linux |
long long, double
| 64 бита (8 байта) |
Побитови оператори
#Аритметичните оператори извършват аритметика върху целите стойности на числата
Побитовите оператори извършват логически операции върху всеки два съответни бита
Побитово "И" &, "ИЛИ" |, "НЕ" ~
#
Работят като логическите &&, ||, ! но върху битовете.
Разглеждайки две еднобайтови числа:
10010011 & 10011100 = 10010000
10010011 | 10011100 = 10011111
~ 10010011 = 01101100
Побитово "изключващо или" ^
#
Истина, когато двата бита са различни и лъжа, когато са еднакви
10010011 ^ 10011100 = 00001111
Отместване наляво <<
#
Отместваме битовете с n на брой позиции на ляво
10010011 << 1 = 00100110
10010011 << 2 = 01001100
10010011 << 3 = 10011000
Отместване надясно >>
#
Отместваме битовете с n на брой позиции на дясно.
Ако типа е unsigned:
10010011 >> 1 = 01001001
10010011 >> 2 = 00100100
Иначе повтаряме водещия бит:
01010011 >> 1 = 00101001
10010011 >> 1 = 11001001
10010011 >> 2 = 11100100
Представяне на цели числа
#- "unsigned" цели числа са ясни (стандартното преобразуване между двоична и десетична бройна система)
- всеки бит репрезентира степен на 2
- как обаче да представим отрицателни числа?
Идея: старшия бит (най-левия) да определя дали е положително или отрицателно
000 0
001 1
010 2
011 3
100 -0
101 -1
110 -2
111 -3
Проблем: нормалното събиране не работи
1 + 1 = 001 + 001 = 010 = 2
1 + -1 = 001 + 101 = 110 = -2
-1 + -1 = 101 + 101 = 1010 = 2 (отрязваме)
Не би ли било готино да представим числата, така че събиране/изваждане да работи по същия начин?
1s complement
#Отрицателното число е като положителното, но с обратните битове
000 0
001 1
010 2
011 3
100 -3
101 -2
110 -1
111 -0
Нарича се така, защото x & -x винаги е равно на 111...111
1 + 1 = 001 + 001 = 010 = 2
1 + -1 = 001 + 110 = 111 = -0
-1 + -1 = 110 + 110 = 1100 = -3 (отрязваме)
Последната сума ни е грешна, защото се нуждаем от "end-around carry". Бита който "прелива" трябва да се събере обратно в числото.
-1 + -1 = 110 + 110 = 1100 = 1 + 100 = 101 = -2
Плюсове: водещия бит е единица при отрицателни.
Минуси: има +0 и -0, нуждаем се от "end-arround carry".
2s complement
#Като 1s complement, но при отрицателните числа изваждаме единица.
000 0
001 1
010 2
011 3
100 -4
101 -3
110 -2
111 -1
Нарича се така, защото x + -x е равно на 2 на степен броя битове
1 + 1 = 001 + 001 = 010 = 2
1 + -1 = 001 + 111 = 1000 = 0 (отрязваме)
-1 + -1 = 111 + 111 = 1110 = -2 (отрязваме)
Събиране/изваждане работят по същия начин, винаги водещия бит е единица при отрицателни, няма -0.
Представяне на числа с плаваща запетая
#Идея: цяло число, в което закодираме позиция на точката.
Например, в 16-битово число, левите 4 бита закодират позицията на точката сред битовете, останалото е числото.
0000 001001010110 -> 001001010110. = 598.0
0010 001001010110 -> 0010010101.10 = 149.2
1010 001001010110 -> 00.1001010110 = 0.598
- Много малък обхват от числа: най-голямо е 4095.0, най-малкото е 0.0, най-прецизното е 0.0001
- Ако използваме 2s complement за отрицателни числа, обхвата става от -2048.0 до 2047.0
- Имаме много нули
- 4те бита за позиция са wasted, защото най-лявата позиция е 12,
1100
IEEE754
#- Формат, публикуван през 1985 година
- За 16 бита, обхвата му е от -65504 до 65504, най-прецизното възможно число е 0.000000059604645
- Поддържа "числата" безкрайност и "not a number"
- Представя числата като дроби (научна нотация)
- Не всички числа в обхвата могат да бъдат представени
- Числата около нулата могат да имат много цифри след запетаята, тези по-далеч могат по-малко
Сложен е, любознателните могат да го разучат: