A számítógép memóriája biteket tárol, ezért a pozitív egész számok mellett a negatív és a törtrészt tartalmazó számokat is 0-k és 1-ek sorozatával kell ábrázolni. Ehhez előre meg kell határozni, hogy az egyes biteknek mi a jelentésük.
Fontos, hogy ugyanaz a bitsorozat önmagában még nem határozza meg a tárolt szám értékét. A 11111111 bitsorozat jelenthet például:
Az értelmezéshez tehát ismernünk kell az adattípust és a felhasznált ábrázolási módot.
Előjel nélküli ábrázolásnál minden bit a szám nagyságát adja meg. Egy 8 bites szám helyiértékei:
| Helyiérték | 2⁷ | 2⁶ | 2⁵ | 2⁴ | 2³ | 2² | 2¹ | 2⁰ |
|---|---|---|---|---|---|---|---|---|
| Érték | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
Például:
00101101₂ = 32 + 8 + 4 + 1 = 45₁₀
n biten összesen 2ⁿ különböző bitminta tárolható. Az előjel nélküli számok értéktartománya:
0 ... 2ⁿ − 1
8 bit esetén ez:
0 ... 255
A negatív számok tárolására többféle módszert dolgoztak ki. A legismertebbek:
A modern számítógépek szinte mindig a kettes komplemens ábrázolást használják az előjeles egész számok tárolására.
Ebben a módszerben a legmagasabb helyiértékű, bal szélső bit az előjelet jelöli:
0: pozitív szám;1: negatív szám.A többi bit a szám abszolút értékét tartalmazza.
8 biten például:
+5 = 00000101 −5 = 10000101
A módszer könnyen értelmezhető, de kétféle nulla tartozik hozzá:
+0 = 00000000 −0 = 10000000
Az összeadás és kivonás végrehajtása is körülményes, mert az előjelet külön kell kezelni. Emiatt egész számok tárolására ma már ritkán használják.
Egy negatív szám egyes komplemensét úgy kapjuk meg, hogy a megfelelő pozitív szám minden bitjét megfordítjuk:
+5 = 00000101 −5 = 11111010
A bitenkénti megfordítás során minden 0-ból 1, minden 1-ből 0 lesz.
Ennél a módszernél is kétféle nulla létezik:
+0 = 00000000 −0 = 11111111
Ez a tulajdonság, valamint az aritmetikai műveletek bonyolultsága miatt az egyes komplemenst a mai általános célú számítógépek egész számok tárolására jellemzően nem használják.
A kettes komplemens ábrázolás előnye, hogy csak egyetlen nullaérték létezik, és ugyanaz az összeadó áramkör használható pozitív és negatív számok összeadására.
Egy negatív szám kettes komplemens alakjának előállítása:
Például a −5 előállítása 8 biten:
00000101 +5 bináris alakja 11111010 a bitek megfordítása + 1 ---------- 11111011 −5 kettes komplemens alakja
Tehát:
+5 = 00000101 −5 = 11111011
Ha egy kettes komplemens számban a bal szélső bit 1, akkor a szám negatív. Az abszolút érték meghatározásához:
Például:
11110110 ismeretlen negatív szám 00001001 a bitek megfordítása + 1 ---------- 00001010 10
Ezért:
11110110₂ = −10₁₀
Egy másik gyors módszer szerint a 8 bites negatív szám bitsorozatát először előjel nélküli számként értelmezzük, majd kivonjuk belőle 2⁸ = 256 értékét:
11110110₂ = 246 előjel nélküli számként 246 − 256 = −10
n bites kettes komplemens szám értéktartománya:
−2ⁿ⁻¹ ... 2ⁿ⁻¹ − 1
Néhány gyakori eset:
| Bitszám | Legkisebb érték | Legnagyobb érték |
|---|---|---|
| 8 bit | −128 | 127 |
| 16 bit | −32 768 | 32 767 |
| 32 bit | −2 147 483 648 | 2 147 483 647 |
| 64 bit | −2⁶³ | 2⁶³ − 1 |
A tartomány azért nem szimmetrikus, mert a nulla is a nemnegatív bitminták egyikét foglalja el. 8 biten például:
01111111 = 127 00000000 = 0 11111111 = −1 10000000 = −128
Kettes komplemens ábrázolásnál a pozitív és negatív számok a szokásos bináris összeadással összeadhatók.
Számítsuk ki 8 biten az 5 + (−3) műveletet:
00000101 +5 + 11111101 −3 ---------- 1 00000010
A kilencedik bitre kerülő átvitelt elhagyjuk, mert a számábrázolás csak 8 bites. Az eredmény:
00000010 = 2
Valóban:
5 + (−3) = 2
Az A − B kivonás elvégezhető úgy, hogy A értékéhez hozzáadjuk B kettes komplemensét:
A − B = A + (−B)
Például 7 − 5:
00000111 +7 + 11111011 −5 ---------- 1 00000010 2
Túlcsordulás akkor történik, ha a matematikai eredmény nem fér el a rendelkezésre álló bitszámon.
8 bites előjeles szám esetén a legnagyobb tárolható érték 127. Ha ehhez 1-et adunk:
01111111 127 + 00000001 1 ---------- 10000000 −128-ként értelmezhető bitminta
A matematikai eredmény 128 lenne, de ez 8 bites előjeles számban nem ábrázolható.
Előjeles összeadásnál túlcsordulás történt, ha:
Különböző előjelű számok összeadásakor nem keletkezhet előjeles túlcsordulás. Az utolsó bitről kilépő átvitel önmagában nem azonos az előjeles túlcsordulással.
Ha egy előjeles számot több biten szeretnénk tárolni, a bal szélső előjelbitet kell megismételni.
Például a −5 átalakítása 8 bitesről 16 bitesre:
8 biten: 11111011 16 biten: 11111111 11111011
Pozitív szám esetén balról 0-kat írunk hozzá:
8 biten: 00000101 16 biten: 00000000 00000101
Ez az előjelkiterjesztés megőrzi a szám eredeti értékét.
A bináris törtek a tízes számrendszer törtrészeihez hasonlóan helyiértékeket használnak, de a tizedesvesszőtől jobbra 2 negatív kitevőjű hatványai állnak.
| Bináris helyiérték | 2⁻¹ | 2⁻² | 2⁻³ | 2⁻⁴ |
|---|---|---|---|---|
| Tízes számrendszerben | 1/2 | 1/4 | 1/8 | 1/16 |
| Érték | 0,5 | 0,25 | 0,125 | 0,0625 |
Például:
0,101₂ = 1 · 2⁻¹ + 0 · 2⁻² + 1 · 2⁻³
= 0,5 + 0 + 0,125
= 0,625₁₀
Egy egész- és törtrészt egyaránt tartalmazó szám:
1101,01₂ = 8 + 4 + 1 + 0,25 = 13,25₁₀
A törtrészt ismételten megszorozzuk 2-vel. Minden lépésben az eredmény egész része adja a következő bináris számjegyet.
Alakítsuk át a 0,625 értéket:
| Művelet | Egész rész | Megmaradó törtrész |
|---|---|---|
| 0,625 · 2 = 1,25 | 1 | 0,25 |
| 0,25 · 2 = 0,5 | 0 | 0,5 |
| 0,5 · 2 = 1,0 | 1 | 0 |
Az egész részeket felülről lefelé összeolvasva:
0,625₁₀ = 0,101₂
Nem minden tízes számrendszerbeli tört írható fel véges bináris törtként. A 0,1 például végtelen, ismétlődő bináris tört:
0,1₁₀ = 0,00011001100110011...₂
Emiatt a számítógép a 0,1 értéknek csak egy közeli közelítését tudja eltárolni.
Törtszámok tárolására többféle megoldás használható.
Fixpontos ábrázolásnál előre meghatározzuk, hogy a bitsorozatban hol található a bináris pont. Például egy 8 bites formátumban kijelölhetünk 4 bitet az egészrész és 4 bitet a törtrész számára. A 00110100 bitsorozat ekkor így értelmezhető:
0011,0100₂ = 3,25₁₀
A fixpontos számok egyszerűek és kiszámítható pontosságúak, de az ábrázolható tartományuk korlátozott.
Lebegőpontos ábrázolásnál a bináris pont helye nem rögzített. A számot a tudományos számábrázoláshoz hasonló alakban tároljuk:
előjel · mantissza · 2kitevő
Például:
1101,01₂ = 1,10101₂ · 2³
A bináris pontot három hellyel mozgattuk balra, ezért a kitevő értéke 3.
A legtöbb mai számítógép az IEEE 754 szabvány szerint tárolja a lebegőpontos számokat. A bitsorozat három mezőből áll:
S – előjelbit (sign);E – eltolt kitevő (exponent);F – törtrészmező (fraction), amelyet gyakran mantisszának is neveznek.A két leggyakoribb formátum:
| Formátum | Teljes méret | Előjel | Kitevő | Törtrész | Kitevő eltolása | Közelítő decimális pontosság |
|---|---|---|---|---|---|---|
| Egyszeres pontosság (float) | 32 bit | 1 bit | 8 bit | 23 bit | 127 | kb. 7 számjegy |
| Kétszeres pontosság (double) | 64 bit | 1 bit | 11 bit | 52 bit | 1023 | kb. 15–16 számjegy |
Egy normál, 32 bites lebegőpontos szám értéke:
(−1)^S · 1,F₂ · 2^(E − 127)
ahol:
S az előjelbit;E a kitevőmező előjel nélküli értéke;F a törtrészmező;Az előjelbit értelmezése:
S = 0: pozitív szám S = 1: negatív szám
A kitevőt eltolva tároljuk, ezért negatív kitevőhöz sincs szükség külön előjelbitre. Például a 3 kitevőt 32 bites formátumban így tároljuk:
3 + 127 = 130 = 10000010₂
Normál számok esetében a mantissza mindig 1, kezdetű. A kezdő 1-est nem kell eltárolni, mert annak értéke ismert. Ezt rejtett egyesnek nevezzük. Így 23 tárolt törtrészbit valójában 24 bites bináris pontosságot biztosít.
13,25₁₀ = 1101,01₂
1101,01₂ = 1,10101₂ · 2³
A szám pozitív:
S = 0
kitevő = 3 eltolt kitevő = 3 + 127 = 130 = 10000010₂
A normalizált alak kezdő 1-esét nem tároljuk. Az utána következő bitek:
10101000000000000000000
S | E | F 0 | 10000010 | 10101000000000000000000
Egybefüggően:
01000001010101000000000000000000
Hexadecimális alakban:
0x41540000
A −13,25 ábrázolásánál csak az előjelbit változik 1-re:
11000001010101000000000000000000 = 0xC1540000
Határozzuk meg a következő 32 bites lebegőpontos szám értékét:
1 | 10000001 | 01100000000000000000000
Az előjelbit:
S = 1, ezért a szám negatív.
A kitevőmező:
10000001₂ = 129 valódi kitevő = 129 − 127 = 2
A rejtett 1-essel kiegészített mantissza:
1,011₂ = 1 + 1/4 + 1/8 = 1,375
A szám értéke:
(−1) · 1,375 · 2² = −1,375 · 4 = −5,5
Az IEEE 754 szabvány bizonyos kitevőmintákat különleges értékek jelölésére tart fenn.
| Kitevőmező | Törtrészmező | Jelentés |
|---|---|---|
| minden bit 0 | minden bit 0 | +0 vagy −0 |
| minden bit 0 | nem minden bit 0 | szubnormális szám |
| 1 és 254 között | tetszőleges | normál szám |
| minden bit 1 | minden bit 0 | +végtelen vagy −végtelen |
| minden bit 1 | nem minden bit 0 | NaN |
Az IEEE 754 formátumban a nullának két előjeles változata van:
+0: S = 0 −0: S = 1
A legtöbb műveletben egyenlőnek számítanak, de bizonyos műveleteknél az előjelüknek lehet jelentősége.
A szubnormális számok segítségével a nullához nagyon közeli értékek is ábrázolhatók. Ezeknél nincs rejtett kezdő 1-es, ezért az értékük:
(−1)^S · 0,F₂ · 2^(1 − bias)
Pontosságuk kisebb, mint a normál számoké, de fokozatos átmenetet biztosítanak a legkisebb normál szám és a nulla között.
Pozitív vagy negatív végtelen keletkezhet például túl nagy eredmény vagy nem nulla érték nullával történő lebegőpontos osztása esetén:
1,0 / 0,0 = +végtelen −1,0 / 0,0 = −végtelen
A NaN jelentése Not a Number, vagyis „nem szám”. Matematikailag nem értelmezett lebegőpontos műveletek eredménye lehet, például:
0,0 / 0,0 négyzetgyök(−1,0) a valós számok között végtelen − végtelen
A NaN különleges tulajdonsága, hogy még önmagával sem tekinthető egyenlőnek:
if (x != x) { /* x értéke NaN */ }
A gyakorlatban azonban erre a célra a programozási nyelvek beépített isnan függvényét célszerű használni.
A lebegőpontos számok véges számú bitből állnak, ezért a valós számoknak csak egy véges részhalmazát tudják pontosan tárolni. A többi értéket a legközelebbi ábrázolható számra kell kerekíteni.
Mivel a 0,1 és a 0,2 nem írható fel véges bináris törtként, a következő összehasonlítás egyes programozási nyelvekben meglepő eredményt adhat:
double a = 0.1; double b = 0.2; if (a + b == 0.3) { printf("Egyenlo"); } else { printf("Nem egyenlo"); }
Az eredmény rendszerint Nem egyenlo, mert a tárolt közelítő értékek összege nem pontosan egyezik meg a 0,3 tárolt közelítésével.
Lebegőpontos értékeket ezért általában egy kis hibahatár, úgynevezett epsilon segítségével hasonlítunk össze:
#include <math.h> double epsilon = 1e-9; if (fabs((a + b) - 0.3) < epsilon) { printf("A ket ertek a megadott pontossagon belul egyenlo"); }
Az epsilon megfelelő értéke a számok nagyságrendjétől és az alkalmazás pontossági követelményeitől függ; nem minden feladathoz jó ugyanaz az állandó.
A lebegőpontos számábrázolás relatív pontosságú. Minél nagyobb számokat tárolunk, annál nagyobb távolság lehet két egymást követő ábrázolható érték között.
A 32 bites float 24 bites bináris pontossága miatt minden egész számot pontosan képes ábrázolni 2²⁴ = 16 777 216 értékig. E fölött már nem minden egymást követő egész szám tárolható.
Például 32 bites float esetén:
16 777 216 még pontosan ábrázolható. 16 777 217 már nem ábrázolható pontosan.
Ezért lebegőpontos típust nem célszerű például nagy azonosítók vagy pénzösszegek pontos tárolására használni.
Túlcsordulás akkor történik, ha az eredmény abszolút értéke nagyobb a formátumban tárolható legnagyobb véges számnál. Az eredmény ilyenkor gyakran pozitív vagy negatív végtelen lesz.
Alulcsordulás akkor történik, ha egy nem nulla eredmény abszolút értéke túl közel kerül a nullához. Az eredmény először szubnormális számmá, végül nullává kerekedhet.
Egyetlen lebegőpontos művelet hibája rendszerint nagyon kicsi, de sok egymás utáni művelet során a hibák felhalmozódhatnak. A műveletek sorrendje is befolyásolhatja az eredményt.
Például nagyon nagy és nagyon kicsi szám összeadásakor a kis szám hatása elveszhet:
nagy_szam + kis_szam = nagy_szam
Ez nem matematikai azonosság, hanem a véges pontosság következménye.
| Tulajdonság | Kettes komplemens egész szám | IEEE 754 lebegőpontos szám |
|---|---|---|
| Tárolható értékek | egészek | törtrészes és nagyon kis vagy nagy számok |
| Pontosság | a tartományon belül pontos | gyakran közelítő |
| Előjel kezelése | a legmagasabb bit helyiértékének része | külön előjelbit |
| Túlcsordulás | a bitsorozat hibás előjelű értékké fordulhat vagy a nyelv hibát jelezhet | gyakran végtelen keletkezik |
| Különleges értékek | általában nincsenek | ±0, ±végtelen, NaN, szubnormális számok |
| Jellemző alkalmazás | számlálók, indexek, darabszámok | mérések, geometriai és tudományos számítások |
n bites egész számok tartománya 0 … 2ⁿ − 1.n bites kettes komplemens számok tartománya −2ⁿ⁻¹ … 2ⁿ⁻¹ − 1.2⁻¹, 2⁻², 2⁻³, … értékek.11101100 bitsorozat 8 bites kettes komplemens számként?12 + (−7) összeadást!100 + 40 összeadás?101,101₂ számot tízes számrendszerbe!10,625₁₀ számot kettes számrendszerbe!45₁₀ = 00101101₂.+18 = 00010010, bitfordítás után 11101101, majd 1 hozzáadásával −18 = 11101110.11101100₂ = −20₁₀.00001100 + 11111001 = 00000101, tehát az eredmény 5.101,101₂ = 5,625₁₀.10,625₁₀ = 1010,101₂.