Számábrázolás


Számábrázolás a számítógépen

A számítógépben a adatokat binárisan, bitek sorozataként ábrázoljuk. A továbbiakban tételezzük fel, hogy az adatokat egy 'n' bites tárolóegységben, ún. regiszterben tároljuk. Mivel ebben egymástól függetlenül 'n' különböző bit tárolható, ez összesen m=2n különböző bitvariációt tesz lehetővé. Tehát egy 'n' bites regiszterben 'm' számú különböző (binárisan kódolt) adatot tárolhatunk. Az 'm' számot a regiszter modulusának is szokás nevezni.
Például
– egy 8 bites regiszter modulusa m=256;
– egy 16 bites regiszter modulusa m=65536;
– egy 24 bites regiszter modulusa m=16,777,216;
– egy 32 bites regiszter modulusa m=4,294,967,296.

Egy 'n' bites regiszterben pontosan m=2n darab különböző binárisan kódolt adat tárolható.

Mivel egy regiszterben biteket tárolunk, egy 'n' bites regiszter egybites tárolóegységek sorozataként is felfogható. Ha bi a regiszter i-dik bitjét jelenti (amelynek értéke 0 vagy 1), akkor egy regisztert
    bn−1bn−2...b2b1b0
formában írhatunk le, ahol bn−1 a legnagyobb sorszámú bit, b0 pedig a legkisebb sorszámú bit.

Számok ábrázolása esetén (vagyis amikor a regiszterben tárolt bitsorozatot számként értelmezzük) a legmagasabb sorszámú bit rendszerint a szám előjelét adja meg:
    bn−1=0 esetén a regiszterben tárolt szám pozitív;
    bn−1=1 esetén a regiszterben tárolt szám negatív.
Ilyenkor a legmagasabb helyiértékű bitet előjelbitnek nevezzük.

Ami egy binárisan ábrázolt szám regiszterbeli elhelyezését illeti, általános szabály, hogy a szám legkisebb helyiértékű bitjét (LSB) a lehető legkisebb sorszámú biten (pl. b0-ban), és ennek megfelelően a szám legnagyobb helyiértékű bitjét (MSB) a lehető legnagyobb sorszámú biten tároljuk.

Megjegyzések:
(1) A "legkisebb sorszámú" és "legnagyobb sorszámú" úgy értendő, hogy a szám ábrázolása mindig pontosan meghatározza, melyek a regiszterben azok a bitek, amelyek a szám számjegyeit tárolják.
(2) Egy több bájton ábrázolt szám bájt szervezésű memóriában történő tárolásakor az egyes bájtok (vagy memóriarekeszek) elhelyezésére rendszerint ugyanezt az elvet követjük, vagyis a kisebb helyiértékű számjegyeket tartalmazó ("kisebb helyiértékű") bájtok memóriacíme mindig kisebb. Az ábrázolt szám, pontosabban a számot tároló bájtok memóriacíme mindig a számhoz tartozó legkisebb című memóriarekesz címe lesz.
(3) Egy több bájton ábrázolt szám fájlba írásakor azonban a bájtok sorrendje legtöbbször (pl. a Java DataOutputStream szűrőjét használva) megfordul, azaz a legnagyobb helyiértékű bájt lesz az első, és a legkisebb helyiértékű bájt az utolsó ("big-endian order").

Ha egy regiszterben számokat tárolunk, a számokat különböző módon feleltethetjük meg a regiszter bitjeinek. Ennek megfelelően a következő kódolási vagy számábrázolási módokról beszélhetünk:

  1. direkt kódolás
  2. kettes komplemens kódolás
  3. binárisan kódolt decimális (BCD) számábrázolás
  4. lebegőpontos számábrázolás

(1) direkt kódolás

Ha egy regiszterben egy bináris számrendszerben ábrázolt nemnegatív egész számot tárolunk úgy, hogy a regiszter bitjeinek a szám bináris számjegyeit feleltetjük meg a helyi értékek megszokott sorrendjében (azaz az LSB-hez a legkisebb, 1-es helyiérték tartozik, majd (jobbról balra haladva) a következő bithez a 2-es helyiérték, utána a 4-es, 8-as stb.), akkor ún. direkt kódolásról (vagy egyenes kódolásról) beszélünk. Mivel direkt kódolás esetén csak nemnegatív számokat ábrázolunk, ezért nincs szükségünk előjelbitre.

Direkt kódolás esetén például egy 8 bites regiszterben tárolható legkisebb szám 0000|00002=010, a legnagyobb pedig 1111|11112=25510.


(2) kettes komplemens kódolás

Tároljunk egy 'n' bites (m=2n modulusú) regiszterben egész számokat a következőképpen:

Ezt a kódolást kettes komplemens kódolásnak nevezzük.

Ábrázoljunk példaként egy 8 bites regiszterben kettes komplemens kódban néhány számot (a bitsorozatok után alsó indexben megadott '2' most kettes komplemens kódban ábrázolt számot jelöl):

decimális érték kettes komplemens kód decimális érték kettes komplemens kód
010 0000|00002
110 0000|00012 −110 1111|11112
210 0000|00102 −210 1111|11102
310 0000|00112 −310 1111|11012
...
2310 0001|01112 −2310 1110|10012
...
12610 0111|11102 −12610 1000|00102
12710 0111|11112 −12710 1000|00012
−12810 1000|00002

Például −2310=1110|10012 mivel 0001|01112=1110|10002 (egyes komplemens) és ehhez 1-et binárisan hozzáadva 1110|10002+12=1110|10012 adódik.
Jegyezzük meg, hogy kettes komplemens kódban 12710 a legnagyobb ábrázolható pozitív szám, és −12810 a legkisebb ábrázolható negatív szám.

Ha képezzük a −2310+2310 összeget 0001|01112+1110|10012=1|0000|00002 adódik, ami éppen a 8 bites regiszter m=256 modulusának 2-es számrendszerben ábrázolt értéke. Általánosan is igaz, hogy egy 'n' bites regiszterben (a megengedett −m/2≤x<m/2 számtartományon belül) egy kettes komplemens kódban ábrázolt negatív szám és a vele abszolút értékben megegyező nemnegatív szám összege a regiszter modulusát adja. Formálisan kifejezve: ha a megengedett számtartományon belül 'v' egy nemnegatív egész számot jelöl, 'w' pedig ennek kettes komplemens kódját, akkor v+w=m vagy másképpen kifejezve v+w=0 (mod m) teljesül.

Két fontos szabály:

Negatív egész számokat kettes komplemens kódban ábrázolva a kivonást összeadásra tudjuk visszavezetni.

Ennek megfelelően kétféle túlcsordulás fordulhat elő:


A fenti algoritmusokat meg valósító JavaScript programok:

(1) Decimális szám kettes komplemens kódban ábrázolt bináris számmá alakítása:

// decimális szám átalakítása kettes komplemens kódban ábrázolt bináris számmá (8 biten)

function dec2bin(x) {
 var b="";
 var q=1;

 while(q>0) {
  q=Math.trunc(x/2); // egész osztás!!
  if(x%2==1) {
   b="1"+b;
   }
  else {
   b="0"+b;
   }
  x=q;
  }

 while(b.length<m) {
  b="0"+b; // vezető 0 hozzáadása
  }
 return b;
 }

function bin2binc(x) {
 var xc="";
 for(var i=0;i<x.length;i++) {
  if(x[i]=="1") {
   xc=xc+"0";
   }
  else {
   xc=xc+"1";
   }
  }
 return xc; 
 }

function inc(x) {
 var xc="";
 var j=x.length-1; // utolsó karakter indexe
 var atvitel=1;
 while(j>=0) {
  if(x[j]=="0" && atvitel==0) {
   xc="0"+xc;
   }
  else if(x[j]=="0" && atvitel==1) {
   xc="1"+xc;
   atvitel=0;
   }
  else if(x[j]=="1" && atvitel==0) {
   xc="1"+xc;
   }
  else {
   xc="0"+xc;
   atvitel=1;
   }
  j=j-1;
  }
 return xc; 
 }

/* feltétel: nyolc biten ábrázoljuk a számokat (m=8), tehát -128<=xd<127 teljesül */

var m=8; // bitek száma
var xd=-127; 
var xb="";

writeln("Decimális szám: "+xd);
writeln();

if(xd>=0) {
 xb=dec2bin(xd);
 }
else {
 var xa,x;
 xd=-xd;
 writeln("Abszolút érték: "+xd);
 writeln();

 xa=dec2bin(xd);
 writeln("Bináris érték:     "+xa);
 x=bin2binc(xa);
 writeln("Egyes komplemens:  "+x);
 xb=inc(x);
 writeln();
 }

writeln("Kettes komplemens: "+xb);

writeln("__________");

(2) Kettes komplemens kódban adott bináris szám decimálissá alakítása:

// kettes komplemens kódban adott (8 bites) bináris szám átalakítása decimális számmá

function bin2dec(x) {
 var d=0;
 var helyiertek=1;

 for(var i=1;i<x.length;i++) {
  helyiertek*=2;
  }

 for(var i=0;i<x.length;i++) {
  var sz;
  if(x[i]=="1") {
   sz=1;
   }
  else {
   sz=0;
   }
  var r=sz*helyiertek;
  d+=r;
  helyiertek/=2;
  }

 return d;
 }

function bin2binc(x) {
 var xc="";
 for(var i=0;i<x.length;i++) {
  if(x[i]=="1") {
   xc=xc+"0";
   }
  else {
   xc=xc+"1";
   }
  }
 return xc; 
 }

function inc(x) {
 var xc="";
 var j=x.length-1; // utolsó karakter indexe
 var atvitel=1;
 while(j>=0) {
  if(x[j]=="0" && atvitel==0) {
   xc="0"+xc;
   }
  else if(x[j]=="0" && atvitel==1) {
   xc="1"+xc;
   atvitel=0;
   }
  else if(x[j]=="1" && atvitel==0) {
   xc="1"+xc;
   }
  else {
   xc="0"+xc;
   atvitel=1;
   }
  j=j-1;
  }
 return xc; 
 }

/* feltétel: nyolc biten ábrázoljuk a számokat (m=8), tehát xb.length=8 teljesül */

var xb="10000001"; 
var s;

writeln("Bináris szám: "+xb);
writeln();

if(xb[0]==0) { // előjelbit pozitív
 s="+";
 }

else { // előjelbit negatív
 s="-";
 var x;
 x=bin2binc(xb);
 writeln("Egyes komplemens: "+x);
 xb=inc(x);
 writeln("Kettes komplemens: "+xb);
 writeln();
 }

writeln("Decimális szám: "+s+bin2dec(xb));

writeln("__________");


(3) binárisan kódolt decimális (BCD) számábrázolás

BCD számábrázolás esetén tízes számrendszerben megadott egész számokat kódolunk a decimális számjegyek adott számú biten történő bináris megadásával. A BCD számábrázolás két típusa:
– pakolt, csomagolt vagy tömörített ("packed") BCD esetén a decimális számjegyeket 4 biten (1 tetrádon) ábrázoljuk (egy bájt felső vagy alsó 4 bitje egy ún. fél bájt vagy tetrád, angolul "nibble");
– pakolatlan, kibontott vagy zónázott ("unpacked") BCD esetén a decimális számjegyeket 8 biten (1 bájton) ábrázoljuk (a felső 4 bitet az ún. zónabitek alkotják, az alsó 4 bit pedig az ábrázolandó decimális számjegy bináris alakját tartalmazza).

Az x86-os architektúra numerikus adatfeldolgozó processzora (NDP) támogatja az előjeles pakolt BCD formátumot. Az így ábrázolt adatok rögzített méretűek (10 bájt hosszúak):
– a jobb szélső 9 bájt tartalmazza a decimális számjegyeket (18 számjegy);
– a bal szélső bájt bal szélső bitje előjelbit: a bit 0 értéke esetén a szám pozitív, 1 értéke esetén a szám negatív (a fennmaradó 7 bit kihasználatlan).

Felhasználva a korábban létrehozott 'dec2bin4' függvényt, a pakolt, előjel nélküli BCD számábrázolást megvalósító algoritmust például a következőképpen írhatjuk le egy JS program segítségével:

// decimális szám átalakítása előjel nélküli pakolt BCD formátumra

function dec2bin4(x) {

var b="";
var q,m;

while(x>0) {
 if(x%2==1) {
  m="1";
  x=x-1;
  }
 else {
  m="0";
  }
 q=x/2;
 b=m+b;
 x=q;
 }

var i=b.length;
while(i<4) {
 b="0"+b; // vezető 0 hozzáadása
 i=i+1;
 }

return b;
} 

var x="314"; 

writeln("Decimális szám: "+x);
writeln();

var i=0;
var bcd="";

while(i<x.length) {
 bcd=bcd+dec2bin4(x[i])+" ";
 i=i+1;
 }

if(x.length%2!=0) {
 bcd="0000"+" "+bcd;
 }

writeln("Pakolt előjel nélküli BCD kód: ");
writeln(bcd);

writeln("__________");

Az előjeles BCD számábrázolást megvalósító algoritmust hasonlóképpen kódolhatjuk:

// decimális szám átalakítása előjeles pakolt BCD formátumra

function dec2bin4(x) {

var b="";
var q,m;

while(x>0) {
 if(x%2==1) {
  m="1";
  x=x-1;
  }
 else {
  m="0";
  }
 q=x/2;
 b=m+b;
 x=q;
 }

var i=b.length;
while(i<4) {
 b="0"+b; // vezető 0 hozzáadása
 i=i+1;
 }

return b;
} 

var x="-314"; 
var sign=0; // alapértelmezésben pozitív
if (x[0]=="-"){
 sign=1;
 };

writeln("Decimális szám: "+x);
writeln();

var i=0;
var bcd="";

while(i<x.length) {
 bcd=bcd+dec2bin4(x[i])+" ";
 i=i+1;
 }

if(x.length%2==0) {
 bcd="0000"+" "+bcd;
 }

if(sign==0) {
 bcd=bcd+"1100"; // hexa 'C' jelzi a pozitív előjelet
 }
else {
 bcd=bcd+"1101"; // hexa 'D' jelzi a negatív előjelet
 }

writeln("Pakolt előjeles BCD kód: ");
writeln(bcd);

writeln("__________");

Az előjel nélküli pakolatlan ("zónázott") BCD számábrázolást megvalósító algoritmus:

// decimális szám átalakítása előjel nélküli pakolatlan BCD formátumra

function dec2bin4(x) {

var b="";
var q,m;

while(x>0) {
 if(x%2==1) {
  m="1";
  x=x-1;
  }
 else {
  m="0";
  }
 q=x/2;
 b=m+b;
 x=q;
 }

var i=b.length;
while(i<4) {
 b="0"+b; // vezető 0 hozzáadása
 i=i+1;
 }

return b;
} 

var x="314"; 

writeln("Decimális szám: "+x);
writeln();

var i=0;
var bcd="";
var zona="1111";

while(i<x.length) {
 bcd=bcd+zona+dec2bin4(x[i])+" ";
 i=i+1;
 }

writeln("Pakolatlan előjel nélküli BCD kód: ");
writeln(bcd);

writeln("__________");

Az előjeles pakolatlan ("zónázott") BCD számábrázolást megvalósító algoritmus pedig a következő:

// decimális szám átalakítása előjeles pakolatlan BCD formátumra

function dec2bin4(x) {

var b="";
var q,m;

while(x>0) {
 if(x%2==1) {
  m="1";
  x=x-1;
  }
 else {
  m="0";
  }
 q=x/2;
 b=m+b;
 x=q;
 }

var i=b.length;
while(i<4) {
 b="0"+b; // vezető 0 hozzáadása
 i=i+1;
 }

return b;
} 

var x="314"; 
var sign=0; // alapértelmezésben pozitív
if (x[0]=="-"){
 sign="1";
 };

writeln("Decimális szám: "+x);
writeln();

var i=0;
var bcd="";
var zona="1111";

while(i<x.length) {
 if(i==x.length-1) { // utolsó bájt
  if(sign==0) {
   zona="1010"; // hexa 'C' jelzi a pozitív előjelet
   }
  else {
   zona="1011"; // hexa 'D' jelzi a negatív előjelet
   }
 }
 bcd=bcd+zona+dec2bin4(x[i])+" ";
 i=i+1;
 }

writeln("Pakolatlan előjeles BCD kód: ");
writeln(bcd);

writeln("__________");



Számábrázolás a számítógépen: lebegőpontos számábrázolás

Lebegőpontos számábrázolás esetén 2-es normál alakban megadott valós számokat kódolunk adott pontossággal. Ennek alapja az, hogy az ábrázolandó 'x' valós számot
x = s*m*2k
normál alakban adjuk meg, ahol 's' a szám előjele (s=±1), 'm' a kettedes tört formában megadott ún. mantissza (m∈ℝ), és 'k' az ún. karakterisztika (k∈ℤ).

A mantissza számjegyeinek (bitjeinek) a száma a számábrázolás pontosságát, a karakterisztika pedig az ábrázolható számok nagyságrendjét határozza meg (vö. Nyakóné Juhász 2011: 21).

A lebegőpontos számok ábrázolása

A továbbiakban az egyszeres pontosságú, 32 bites lebegőpontos számábrázolással foglalkozunk. (Az Institute of Electrical and Electronics Engineers (IEEE) által a nyolcvanas években kiadott IEEE 754 nevű szabvány alapján, vö. Nyakóné Juhász 2011: 21-22).

Ha egyszeres pontossággal, 32 biten ábrázolunk egy lebegőpontos számot, akkor
– az előjelet a bal szélső 1 biten a szokásos módon,
– a karakterisztikát a következő 8 biten többletes kódolással,
– a mantisszát pedig a fennmaradó 23 biten fixpontos kódolással
ábrázoljuk.

b b b ... b b b b b b b ... b b b
előjel (sign, 1 bit)
karakterisztika (exponent, 8 bit)
mantissza (fraction, 23 bit)

Jelöljük
– az ábrázolt valós számot 'x'-szel;
– a karakterisztika tényleges értékét 'k'-val, az egyszeres pontosságú lebegőpontos számnak a karakterisztika számára fenntartott 8 bitjén direkt kódolással ábrázolt "többletes" (127-tel, ill. kis számok esetén 126-tal eltolt) értéket pedig exp-val;
– a mantissza tényleges értékét 'm'-mel, az egyszeres pontosságú lebegőpontos számnak a mantissza számára fenntartott 23 bitjén fixpontos kódolással ábrázolt értéket pedig frac-val.

Három esetet különböztetünk meg:

(1) "normál" eset: a karakterisztika legalább −126, és az ábrázolt exponens legalább 1 (vagyis nem zérus)

Normál esetben az ábrázolandó 'x' valós számra
    |x|≥2−126≈1.1754943508222875079687365372222*10−38
teljesül.

Ha az ábrázolandó valós számra 2−126≤|x|<2128 teljesül, akkor

Ha a karakterisztika (k) kódolt értéke nem zérus (vagyis a karakterisztika −126-nál nem kisebb egész szám), a mantissza tényleges értékét (m) egy olyan kettedes törttel fejezzük ki, amelynek egész része mindig 1 (vagyis a mantissza 1≤m<2 közötti valós szám). Az egyszeres pontosságú lebegőpontos számnak a mantissza számára fenntartott 23 bitje ilyenkor a mantissza tört részének bináris számjegyeit adja meg.

Megjegyzések:
– a karakterisztika tényleges értékének (k) fenti módon történő kódolását ún. 127-es többletes kódolásnak nevezzük (ez k+127 direkt kódban történő ábrázolását jelenti adott számú (ti. 8) biten);
– a kettedestörtek számjegyeinek (az egész résznek és/vagy a tört résznek) adott számú biten történő ábrázolását nevezzük ún. fixpontos számábrázolásnak (a mantissza ábrázolása ezt a kódolási formát követi, mivel a mantissza tört részének bináris számjegyeit rögzített számú (ti. 23) biten adjuk meg);
– az (1) esetben ábrázolható legkisebb szám esetén exp=1 és frac=0, tehát
    x(1),min=1.0000...*2−126=2−126;
– az (1) eset ekvivalens azzal, amikor a karakterisztika −125≤k≤128 közötti egész szám és a mantissza 1/2≤m<1 közötti valós szám (vagyis a mantisszát 0.1-re normáljuk). Ekkor a karakterisztikát 8 biten 126-os többletes kódban adjuk meg, azaz az exp=k+126 egész számot ábrázoljuk direkt kódban (1≤exp≤254), és a mantissza kettedestört alakjában a mantissza 0.1 utáni bináris számjegyeit ábrázoljuk a rendelkezésre álló 23 biten.

(2) a zérushoz közeli ("kis") számok esete: a karakterisztika −126, és az ábrázolt exponens zérus

Zérushoz közeli számok esetén az ábrázolandó 'x' valós számra
    |x|<2−126≈1.1754943508222875079687365372222*10−38
teljesül.

Ha az ábrázolandó valós számra 0≤|x|<2−126 teljesül, akkor

Ha a karakterisztika (k) kódolt értéke zérus (vagyis a karakterisztika értéke −126), a mantissza tényleges értékét (m) egy olyan kettedes törttel fejezzük ki, amelynek egész része mindig 0 (vagyis a mantissza 0≤m<1/2 közötti valós szám). Az egyszeres pontosságú lebegőpontos számnak a mantissza számára fenntartott 23 bitje ilyenkor is a mantissza tört részének bináris számjegyeit adja meg. Ha a mantissza értéke zérus, akkor a lebegőpontos szám értéke is zérus (az előjeltől függetlenül).

Megjegyzések:
– ha az (1) esetben a mantisszát 0.1-re normáljuk (azaz 1/2≤m<1 teljesül), akkor a (2) eset annak a speciális esetnek felel meg, amikor a karakterisztika k=−126 (és exp=0); de mivel szeretnénk a zérust is ábrázolni, most megengedjük az 1/2-nél kisebb nemnegatív mantisszákat is (vagyis ebben az esetben 0≤m<1 teljesül);
– a (2) esetben alkalmazott kódolás lehetővé teszi a zérus ábrázolását ("lebegőpontos nulla"), sőt valójában ez kétféleképpen is lehetséges: ha az egyszeres pontosságú lebegőpontos számok számára rendelkezésre álló 32 biten csupa 0 szerepel, "pozitív" zérusról, ha pedig az első bit 1, és utána 31 biten csupa 0 szerepel, "negatív" zérusról beszélhetünk;
– a (2) esetben ábrázolható legnagyobb szám m=0.1111... és exp=0 (azaz k=−126) miatt
    x(2),max=0.1111...*2−126≲2−126.

(3) túlcsordulás: a karakterisztika legalább 128, és az ábrázolt exponens 255 (azaz binárisan 1111|1111) (az abszolút értékben "túlságosan" nagy, ezért lebagőpontosan már nem ábrázolható számok esete)

Ha az ábrázolandó számra 2128≤|x| teljesül, akkor a valós szám már nem ábrázolható az egyszeres pontosságú lebegőpontos formátumban. Ekkor

Túlcsorduláskor az ábrázolt bitsorozatot a mantissza értékétől függetlenül nem számként értelmezzük, hanem az előjelbittől függően plusz, ill. minusz végtelenként (±∞). A túlcsordulás szokásos jelölése NaN ("not a number").

1. példa (vö. Nyakóné Juhász 2011: 22): Tekintsük az alábbi 32 bites bitsorozatot, amely egy egyszeres pontosságú lebegőpontos számot határoz meg:
    x=1 10000111 101000000000000000000002
Határozzuk meg, ez milyen valós számnak felel meg!

A lebegőpontos számábrázolás (1) esetét alapul véve
– mivel az előjelbit 1, ezért 'x' negatív;
– mivel k'=1000|01112=13510, ezért a karakterisztika értéke k=k'−127=8;
– mivel az 1-re normált mantissza m=1.101000...2, ezért
m=1+1/2+1/8=8/8+5/8=13/8

Tehát a keresett valós szám 28=256 miatt
x=−13/8*28=−13/8*256=−416

Vizsgáljuk meg azt az esetet, amikor a mantisszát 0.1-re normáljuk. Ekkor a következőket kapjuk:
– mivel az előjelbit 1, ezért 'x' negatív;
– mivel k'=1000|01112=13510, ezért a karakterisztika értéke k=k'−126=9;
– mivel a 0.1-re normált mantissza m=0.1101000...2, ezért
m=1/2+1/4+1/16=8/16+4/16+1/16=13/16
Tehát a keresett valós szám 29=512 miatt
x=−13/16*29=−13/16*512=−416
megegyezik az előző értékkel.


Az algoritmus egyszerű megvalósításához fel fogjuk használni a JavaScript nyelv Math.pow(x,k) függvényét, amely egy 'x' szám 'k'-dik hatványát (azaz xk értékét) számolja ki. A fenti algoritmust megvalósító JavaScript program ezek után a következő:

// lebegőpontos számot ábrázoló bináris számsorozat átalakítása decimális számmá (1. példa)

function bin2dec(x) {
 var d=0;
 var helyiertek=1;

 for(var i=1;i<x.length;i++) {
  helyiertek*=2;
  }

 for(var i=0;i<x.length;i++) {
  var sz;
  if(x[i]=="1") {
   sz=1;
   }
  else {
   sz=0;
   }
  var r=sz*helyiertek;
  d+=r;
  helyiertek/=2;
  }

 return d;
 }

function binf2decf(x) {
 var d=0;
 var helyiertek=1/2;

 for(var i=0;i<x.length;i++) {
  var sz;
  if(x[i]=="1") {
   sz=1;
   }
  else {
   sz=0;
   }
  var r=sz*helyiertek;
  d+=r;
  helyiertek/=2;
  }

 return d;
 }

/* feltétel: exp>0 vagyis a lebegőpontos számábrázolás (1) esetének megfelelő algoritmust valósítjuk meg */

var s="1";
var exp="10000111";
var frc="10100000000000000000000"; 

writeln("Lebegőpontos szám: "+s+" "+exp+" "+frc);
writeln();

var e;
var k;
var m;

if(s=="0") {
 e=1;
 }
else {
 e=-1;
 }

k=bin2dec(exp)-127;

m=1+binf2decf(frc);

writeln("Előjel: "+e);
writeln("Karakterisztika: "+k);
writeln("Mantissza: "+m);
writeln();

var d=e*Math.pow(2,k)*m;

writeln("Decimális szám: "+d);

writeln("__________");


2. példa: Tekintsük az alábbi 32 bites bitsorozatot, amely most is egy egyszeres pontosságú lebegőpontos számot határoz meg:
    x=0 00000000 101000000000000000000002
Határozzuk meg, ez (közelítőleg) milyen valós számnak felel meg!

A lebegőpontos számábrázolás (2) esetét alapul véve
– mivel az előjelbit 0, ezért 'x' pozitív;
– mivel k'=0000|00002=010, ezért a karakterisztika értéke k=k'−126=−126;
– mivel a 0.-val kezdődő mantissza m=0.101000...2, ezért
m=1/2+1/8=5/8

Tehát a keresett valós szám
x=5/8*2−126≈7.3468...10−39


A fenti algoritmust megvalósító JavaScript program:

// lebegőpontos számot ábrázoló bináris számsorozat átalakítása decimális számmá (2. példa)

function binf2decf(x) {
 var d=0;
 var helyiertek=1/2;

 for(var i=0;i<x.length;i++) {
  var sz;
  if(x[i]=="1") {
   sz=1;
   }
  else {
   sz=0;
   }
  var r=sz*helyiertek;
  d+=r;
  helyiertek/=2;
  }

 return d;
 }

/* feltétel: exp=0 vagyis a lebegőpontos számábrázolás (2) esetének megfelelő algoritmust valósítjuk meg */

var s="0";
var exp="00000000";
var frc="10100000000000000000000"; 

writeln("Lebegőpontos szám: "+s+" "+exp+" "+frc);
writeln();

var e;
var k;
var m;

if(s=="0") {
 e=1;
 }
else {
 e=-1;
 }

k=-126;

m=binf2decf(frc);

writeln("Előjel: "+e);
writeln("Karakterisztika: "+k);
writeln("Mantissza: "+m);
writeln();

var d=e*Math.pow(2,k)*m;

writeln("Decimális szám: "+d);

writeln("__________");


3. példa: Tekintsük az alábbi valós számot:
    x=7.510
Határozzuk meg, a szám lebegőpontos ábrázolása milyen bitekből áll!

A szám lebegőpontos ábrázolása x≫2−126 miatt egészen nyilvánvalóan a normál esetnek felel meg.

A fentiek alapján x=7.5 lebegőpontosan ábrázolt alakja
    x= 0 10000001 11100000000000000000000 2
formában fejezhető ki.


A fenti algoritmust megvalósító JavaScript program:

// decimális szám átalakítása lebegőpontos számot ábrázoló bináris számsorozattá

function dec2bin(x,maxi) {
 var b="";
 var helyiertek=1;
 
 while(2*helyiertek<=x) {
  helyiertek*=2;
  }
 
 while(helyiertek>=1) {
  if(helyiertek<=x) {
   b+="1";
   x-=helyiertek;
   }
  else {
   b+="0";
   }
  helyiertek/=2;
  }
 
 while(b.length<maxi) {
  b="0"+b; // vezető 0
  }
 return b;
 }

function decf2binf(x,maxi) {
 var s="";
 
 var i=1;
 while(x>0 && i<=maxi) {
  x*=2;
  if(x<1) {
   s+="0";
   }
  else {
   s+="1";
   x=x-1;
   }
  i++;
  }

 while(s.length<maxi) {
  s=s+"0" // záró 0
  }
 return s;
 }

/* feltétel: x abszolút értéke elegendően nagy (x>>0); a lebegőpontos számábrázolás normál (1) esetének megfelelő algoritmust valósítjuk meg */

var x=7.5;
// var x=-0.15;

writeln("Ábrázolandó decimális szám: "+x);
writeln();

var s;
var exp;
var frc; 

var e;
var k;
var m;

if(x>0) {
 e=1;
 s="0";
 }
else {
 e=-1;
 s="1";
 x=-x; // abszolút érték
 }

k=0;
if(x>=2) {
 while(x>=2) {
  x=x/2;
  k=k+1;
  }
 }
else if(x<1) {
 while(x<1) {
  x=x*2;
  k=k-1;
  }
 }

exp=dec2bin(k+127,8);

m=x;
frc=decf2binf(m-1,23);

writeln("Előjel: "+e);
writeln("Karakterisztika: "+k);
writeln("Mantissza: "+m);
writeln();

// var d=e*Math.pow(2,k)*m;
// writeln("Ábrázolandó decimális szám: "+d);

writeln("Lebegőpontos szám: "+s+" "+exp+" "+frc);

writeln("__________");




Tartalom
Boda István, 2023.