Download as pdf or txt
Download as pdf or txt
You are on page 1of 33

Tölvutækni og forritun

Fyrirlestur 5: Bitar og heiltölur

Hjálmtýr Hafsteinsson
Haust 2021
Byggt á glærum eftir Bryant og O'Hallaron

"Verið dugleg að skoða


kennslubókina, hún er mjög góð."
Atli, haust '19
Í þessum fyrirlestri
• Táknun upplýsinga sem bitar
• Aðgerðir á bita 2.1

• Táknun heiltalna í tölvum


– Án formerkis (unsigned) 2.2.1 - 2.2.5

– Með formerki (signed)


– Notkun í C
Allt er bitar
Erum í raun að vinna með
• Hver biti er 0 eða 1 tvær stöður (states)

• Með kóðun og túlkun bitastrengja er hægt að:


– stýra tölvunni (skipanir)
– tákna tölur, strengi, myndir, ... (gögn)
• Af hverju bitar?
– Auðvelt að geyma á fjölbreyttu formi
– Öryggi í sending þrátt
fyrir suð og ónákvæma 0 1 0

miðla 1.1V
0.9V

0.2V
0.0V
Getum talið í tvíundarkerfi
• Táknum tölur með grunninum 2
Heiltala (integer)

– Táknum 30910 sem 1001101012


Tugabrot (decimal)

– Táknum 1.2010 sem 1.001100110011[0011]…2

– Táknum 1.5213 X 104 sem 1.11011011011012 X 213


Kommutala með fljótandi
kommu (floating point)
Kóðun bætagilda
• Bæti = 8 bitar 0 0 0000
– Tvíundar: 000000002 til 111111112 1
2
1
2
0001
0010
3 3 0011
– Tugakerfi: 010 til 25510 4 4 0100
5 5 0101
– Sextándakerfi: 0016 til FF16 6 6 0110
• Talnakerfi með grunninn 16 7 7 0111
8 8 1000
• Notum táknin ‘0’ til ‘9’ og ‘A’ til ‘F’ 9 9 1001
A 10 1010
• Skrifum FA1D37B16 í C sem B 11 1011
0xFA1D37B C 12 1100
D 13 1101
E 14 1110
15213: 0011 1011 0110 1101 F 15 1111

3 B 6 D
Sextándakerfið (Hex)
• Oft notað í stað tvíundarkerfisins
– Auðvelt að breyta fram og til baka
• Hver sextándastafur er 4 bitar
• Breyting úr/í tugakerfið er flóknari
– Krefst margföldunar/deilingar

1227 = 76*16 + 11 (B)


76 = 4*16 + 12 (C)
4 = 0*16 + 4 (4)
Framsetning í C:
122710 = 4CB16 0X4CB
0x4cb
Orðastærð (word size)
• Orðastærð tölvu ræður minnisstærð
– Stærð benda ákvarðar hversu mörg hólf er hægt að vísa í
• Í dag eru flestar tölvur með 64-bita orðstærð
– 32-bita bendar geta bara vísað í 4 GB
– Með 64-bita bendum er hægt að vísa í 16 exabæti
• Skipanamengi breytist líka u.þ.b. 1.84 x 1019 bæti
– IA32 skipanir vinna með 32-bita orð
– x86-64 skipanir vinna með 64-bita orð

Örgjörvar innihalda reyndar


bæði skipanamengin!
Táknun gagna í C
Gagnatag í C 32-bita útgáfa 64-bita útgáfa x86-64

char 1 1 1
short 2 2 2
int 4 4 4
long 4 8 8
float 4 4 4
double 8 8 8

bendir 4 8 8
Boole-algebra
• Sett fram af George Boole í kringum 1850
– Algebruleg framsetning á rökfræði
• Kóðum “Satt” sem 1 og “Ósatt” sem 0
OG EÐA
◼ A&B = 1 þegar bæði A=1 og B=1 ◼ A|B = 1 þegar A=1 eða B=1

EKKI
Annaðhvort-eða (Xor)
◼ ~A = 1 þegar A=0
◼A^B = 1 þegar annað hvort A=1
eða B=1, ekki bæði
Almennar Boole-algebrur
• Vinna á bitafylkjum
– Aðgerðirnar vinna á hvern bita fyrir sig (bitwise)
01101001 01101001 01101001
& 01010101 | 01010101 ^ 01010101 ~ 01010101
01000001
01000001 01111101
01111101 00111100
00111100 10101010
10101010

• Allir venjulegir eiginleikar Boole-algebra eru


óbreyttir
Táknun og aðgerðir á mengi

• Táknun
– Bitafylki af stærð w táknar hlutmengi í {0, …, w–1}
– aj = 1 þþaa j ∈ A
01101001 { 0, 3, 5, 6 } 01010101 { 0, 2, 4, 6 }
76543210 76543210

• Aðgerðir
– & Sniðmengi 01000001 { 0, 6 }
– | Sammengi 01111101 { 0, 2, 3, 4, 5, 6 }
– ^ Samhverfur mengjamunur 00111100 { 2, 3, 4, 5 }
– ~ Fylling 10101010 { 1, 3, 5, 7 }
Bitaaðgerðir í C
• Virkjarnir &, |, ~, ^ eru í C
– Vinna með öll grunngagnatög 0 0 0000
• long, int, short, char, unsigned 1 1 0001
2 2 0010
– Viðföng tekin sem bitafylki 3 3 0011
– Aðgerðum beitt bita fyrir bita (bitwise) 4 4 0100
5 5 0101
• Dæmi (gagnatagið char) 6 6 0110
7 7 0111
– ~0x41 → 0xBE 8 8 1000
• ~010000012 → 101111102 9 9 1001
– 0x69 & 0x55 → 0x41 A 10 1010
• 011010012 & 010101012 → 010000012 B 11 1011
C 12 1100
– 0x69 | 0x55 → 0x7D D 13 1101
• 011010012 | 010101012 → 011111012 E 14 1110
F 15 1111
Bitaaðgerðir í C
• Virkjarnir &, |, ~, ^ eru í C
– Vinna með öll grunngagnatög 0 0 0000
• long, int, short, char, unsigned 1 1 0001
2 2 0010
– Viðföng tekin sem bitafylki 3 3 0011
– Aðgerðum beitt bita fyrir bita (bitwise) 4 4 0100
5 5 0101
• Dæmi (gagnatagið char) 6 6 0110
7 7 0111
– ~0x41 → 0xBE 8 8 1000
• ~010000012 → 101111102 9 9 1001
– 0x69 & 0x55 → 0x41 A 10 1010
• 011010012 & 010101012 → 010000012 B 11 1011
C 12 1100
– 0x69 | 0x55 → 0x7D D 13 1101
• 011010012 | 010101012 → 011111012 E 14 1110
F 15 1111
Rökvirkjar í C
• Berum saman við rökvirkjana: &&, ||, !
– Túlka 0 sem “Ósatt”
Ruglið ekki saman && og &
– Allt sem er ekki-núll er “Satt” (|| og |). Algeng uppspretta
– Skila alltaf 0 eða 1 erfiðra forritunarvilla í C
– Skammhlaup (short circuit) í rökyrðingum
• Dæmi (gagnatagið char)
if (p && fun(*p)) ...
– !0x41 → 0x00
– !0x00 → 0x01
Kemur í veg fyrir
– !!0x41→ 0x01 notkun á null-bendi
– 0x69 && 0x55 → 0x01
– 0x69 || 0x55 → 0x01
Hliðrunarvirkjar
• Vinstri hliðrun: x << y Viðfang x 01100010
– Hliðra bitafylki x til vinstri um y sæti << 3 00010000
• Henda burtu aukabitum til vinstri
Rökf. >> 2 00011000
• Fylla með 0-um hægra megin
• Hægri hliðrun: x >> y Reikn. >> 2 00011000

– Hliðra bitafylki x til hægri um y sæti


• Henda burtu aukabitum til hægri Viðfang x 10100010
– Rökfræðihliðrun (logical shift) << 3 00010000
• Fylla með 0-um vinstra megin
Rökf. >> 2 00101000
– Reiknihliðrun (arithmetic shift)
• Endurtaka bitann sem er lengst til vinstri Reikn. >> 2 11101000

Óskilgreind hegðun ef hliðrun <0 eða of stór


Kóðun heiltalna
Án formerkis (unsigned) Tvíandhverfa (two’s complement)
w−1
w−2
B2U(X) =  xi 2 i B2T(X) = −xw−1 2 w−1
+  xi 2i
i=0
i=0

• C krefst ekki notkunar á tvíandhverfu Formerkisbiti


– Við munum þó gera ráð fyrir því
short int x = 15213;
• Gagnatagið short í C er 2 bæti short int y = -15213;

Decimal Hex Binary


x 15213 3B 6D 00111011 01101101
y -15213 C4 93 11000100 10010011

• Í tvíandhverfu gefur efsti bitinn til kynna formerkið


– 0 þýðir ekki neikvæð, 1 þýðir neikvæð
Tvíandhverfa - einfalt dæmi

-16 8 4 2 1
8+2 = 10
10 = 0 1 0 1 0

-16 8 4 2 1
-16+4+2 = -10
-10 = 1 0 1 1 0
Tvíandhverfa - dæmi
Weight 15213 -15213
1 1 1 1 1
x = 15213: 00111011 01101101 2 0 0 1 2
y = -15213: 11000100 10010011 4 1 4 0 0
8 1 8 0 0
16 0 0 1 16
32 1 32 0 0
64 1 64 0 0
128 0 0 1 128
256 1 256 0 0
512 1 512 0 0
1024 0 0 1 1024
2048 1 2048 0 0
4096 1 4096 0 0
8192 1 8192 0 0
16384 0 0 1 16384
-32768 0 0 1 -32768
Sum 15213 -15213
Myndræn sýn

– 23 = –8
23 =8 22 = 4
22 = 4 21 = 2
21 = 2 20 = 1
20 = 1 –8 –7 –6 –5 –4 –3 –2 –1 0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
[0001]
[0001] [0101]
[0101]
[1011]
[1011]
[1111] [1111]

Heiltala án formerkis (unsigned) Tvíandhverfu heiltala (2's complement)

Fremsti bitinn er formerkisbiti


og er notaður til að búa til
neikvæðar tölur
Talnabil
• Gildi án formerkis (unsigned) • Tvíandhverfugildi
– UMin = 0 – TMin = –2w–1
000…0 100…0
– UMax = 2w – 1 – TMax = 2w–1 – 1
111…1 011…1
– Mínus 1
111…1
Gildi fyrir w = 16
Decimal Hex Binary
UMax 65535 FF FF 11111111 11111111
TMax 32767 7F FF 01111111 11111111
TMin -32768 80 00 10000000 00000000
-1 -1 FF FF 11111111 11111111
0 0 00 00 00000000 00000000
Gildi fyrir mismunandi orðastærðir
W
8 16 32 64
UMax 255 65,535 4,294,967,295 18,446,744,073,709,551,615
TMax 127 32,767 2,147,483,647 9,223,372,036,854,775,807
TMin -128 -32,768 -2,147,483,648 -9,223,372,036,854,775,808

• Athugið: • C forritun
– #include <limits.h>
– |TMin | = TMax + 1
– Skilgreinir fasta, t.d.:
• Ósamhverft talnabil
• ULONG_MAX
– UMax = 2 * TMax + 1 • LONG_MAX
• LONG_MIN
– Gildin fara eftir umhverfinu
Talnagildi með/án formerkis
X B2U(X) B2T(X)
0000 0 0
• Jafngildi
0001 1 1 – Sama kóðun fyrir jákvæð gildi
0010 2 2
0011 3 3
• Einkvæmni
0100 4 4 – Hvert bitamynstur táknar ólíka
0101 5 5 heiltölu
0110 6 6
– Hver táknanleg heiltala hefur
0111 7 7
1000 8 –8 einkvæmt bitamynstur
1001 9 –7 •  Getum snúið vörpunum við
1010 10 –6
1011 11 –5
– U2B(x) = B2U-1(x)
1100 12 –4 • Bitamynstur fyrir jákvæða heiltölu
1101 13 –3 – T2B(x) = B2T-1(x)
1110 14 –2
• Bitamynstur fyrir tvíandhverfa heiltölu
1111 15 –1
Tala án formerkis ↔ tvíandhverfu tala

Tvíandhverfa T2U Án formerkis


x T2B B2U ux
X

Halda sama bitamynstri

Án formerkis U2T Tvíandhverfa


ux U2B B2T x
X

Halda sama bitamynstri

• Varpanir á milli talna án formerkis og tvíandhverfu talna:


Óbreytt bitamynstur, en breytt túlkun
Með formerki  Án formerkis
Bitar Með formerki Án formerkis
0000 0 0
0001 1 1
0010 2 2
0011 3 3
0100 4 4
0101 5 5
0110 6 T2U 6
0111 7 U2T 7
1000 -8 8
1001 -7 9
1010 -6 10
1011 -5 11
1100 -4 12
1101 -3 13
1110 -2 14
1111 -1 15
Með formerki  Án formerkis
Bitar Með formerki Án formerkis
0000 0 0
0001 1 1
0010 2 2
0011 3 = 3
0100 4 4
0101 5 5
0110 6 6
0111 7 7
1000 -8 8
1001 -7 9
1010 -6 10
+/- 16
1011 -5 11
1100 -4 12
1101 -3 13
1110 -2 14
1111 -1 15
Tölur með/án formerkis

Tvíandhverfa T2U Án formerkis


x T2B B2U ux
X

Halda sama bitamynstri

w–1 0
ux + + + ••• + + +

x - + + ••• + + +

Stórt neikvætt vægi


verður
Stórt jákvætt vægi
Myndræn útgáfa af breytingu
• Tvíandh. → Án formerkis UMax
UMax – 1
– Snúum við röðinni
– Neikvæð → Stór jákvæð
Bil án
TMax + 1
formerkis
TMax TMax

Tvíandhverfubil 0 0
–1
–2

TMin
Heiltölur með formerki í C
• Fastar eru sjálfkrafa með formerki
– Heiltölur án formerkis verða að hafa "U" aftast
0U, 4294967259U

• Getum kastað (cast) á milli talna með/án formerkis


int tx, ty;
unsigned ux, uy;
tx = (int) ux;
uy = (unsigned) ty;

– Sjálfkrafa köstun verður líka í gildisveitingum og fallsköllum:


tx = ux; int fun(unsigned u);
uy = ty; uy = fun(tx);
Óvæntir hlutir í köstun
• Útreikningur segða:
– Ef það er blanda af heiltölum með og án formerkis
(signed / unsigned) í einni reiknisegð, þá er:
gildum með formerki sjálfkrafa kastað í gildi án
formerkis (signed → unsigned)
– Skiptir ekki svo miklu máli fyrir útreikningsaðgerðir
• Reikniaðgerðirnar virka eins (sjáum á eftir!)
– Getur skipt máli fyrir samanburðaraðgerðirnar
<, >, ==, <=, >=
Dæmi um óvænt köst
• Dæmi um samanburð fyrir W = 30:
TMIN = -2,147,483,648 , TMAX = 2,147,483,647
• Fasti1 Fasti2 Vensl Útreikningur
0 0U == unsigned
-1 0 < signed
-1 0U > unsigned
2147483647 -2147483647-1 > signed
2147483647U -2147483647-1 < unsigned
-1 -2 > signed
(unsigned)-1 -2 > unsigned
2147483647 2147483648U < unsigned
2147483647 (int)2147483648U > signed
Algeng mistök
unsigned i;
for (i = cnt-2; i >= 0; i--)
a[i] += a[i+1];
Breytan i verður aldrei < 0,
því hún er án formerkis!

– Getur verið mjög lúmskt: Fallið sizeof() skilar tölu


án formerkis (unsigned)
#define DELTA sizeof(int)
int i;
for (i = CNT; i-DELTA >= 0; i-= DELTA)
. . .
Breytan i er með formerki, en hér er
útreikningur með tölu sem er án formerkis,
svo útkoman getur aldrei orðið neikvæð!
Samantekt á formerkisköstun

• Helstu reglur:
– Bitamynstur halda sér
– ... en eru túlkuð á annan hátt
– Getur hafa óvæntar afleiðingar:
• Samlagning eða frádráttur á 2w

– Segðir með signed int og unsigned int:


• int er kastað yfir í unsigned!!
Fyrirlestraæfingar
1. Reiknið: 0xA03B + 0x84
2. Ef a inniheldur 0x47 og b inniheldur 0x52
reiknið C segðirnar:
~a | b
~a || b
3. Hvert er gildið á bætinu 0xB sem tala án
formerkis (unsigned) og sem tvíandhverfutala
(signed)?

You might also like