Sistemi di Numerazione a Base fissa

Sistema Decimale

Sistema Binario Proposta di Lavoro N°1

Sistema Ottale

Sistema Esadecimale

Proposta di Lavoro N°2 (programma di conversione di un numero binario in decimale e viceversa)

Sistemi di numerazione a base fissa

Un sistema di numerazione è un insieme di regole e simboli il cui utilizzo permette di rappresentare delle quantità.

Per definire un sistema a base fissa si può affermare che deve essere composto da:

un numero maggiore di uno che costituisce la base e che indicheremo con B;

un insieme di simboli che rappresentano i numeri a partire da zero fino al numero precedente la base (B simboli in tutto);

ogni numero è rappresentato con una sequenza di simboli in modo posizionale, in altre parole le cifre, secondo la posizione nel numero, assumono un valore ben preciso e diverso da quello delle cifre precedenti o successive (punto radice = punto decimale).

Ordine di grandezza Ak ... A2 A1 A0 · A-1 A-2 ... A-n
Posizione k ... 2 1 0 · -1 -2 ... -n
Valore posizionale Bk ... B2 B1 B0 · B-1 B-2 ... B-n

Tutti i sistemi di numerazione posizionale a base fissa, indipendentemente dalla base prescelta per la rappresentazione, soddisfano alle seguenti caratteristiche:

sono sistemi non ridondanti, non vi sono quindi sequenze di simboli che non rappresentano alcun numero;

sono a rango illimitato, in altre parole ogni numero può essere rappresentato, non importa quanto grande o piccolo sia;

sono a rappresentazione unica, in altre parole ogni numero ha una sola rappresentazione, costituita da un insieme ordinato di cifre.





SISTEMA DECIMALE

Base: numero di simboli del sistema í 0, 1, 2, 3, 4, 5, 6, 7, 8, 9ý

Rappresentazione polinomiale:

grado (N - 1), dove N è il numero di cifre della parte intera.

838.34= 8*102+3*101+8*100+3*10-1+4*10-2 = 800+30+8+0.3+0.04







SISTEMA BINARIO

Base: numero di simboli del sistema í 0, 1ý

Corrispondenza con gli stati dei dispositivi elettronici che possono assumere solo due livelli: basso (0), alto (1). È importante mettere in evidenza che non contano i valori assoluti dei livelli, ma conta soprattutto questa duplice possibilità che può essere associata ai seguenti pensieri logici: vero o falso, spento o acceso, ON e OFF.

Maggior numero di cifre per rappresentare lo stesso numero in un altro sistema.

LSB (Least Significant Bit), bit meno significativo.

MSB (Most Significant Bit), bit più significativo.

ADDIZIONE: le regole della somma danno i seguenti risultati.

  0 + 0 = 0  
  0 + 1 = 1  
  1 + 0 = 1  
  1 + 1 = 0 CARRY = 1

Un esempio chiarirà meglio il modo di esecuzione di una somma aritmetica.

1 1 1 1        
  1 1 0 1 0 0 +
    1 1 1 0 1  
------------------------------------------
1 0 1 0 0 0 1  

SOTTRAZIONE

DIRETTA: le regole della sottrazione diretta danno i seguenti risultati.

  0 - 0 = 0  
  1 - 0 = 1  
  1 - 1 = 0  
  0 - 1 = 1 BORROW = 1

Un esempio chiarirà meglio il modo di esecuzione di una sottrazione diretta.

             
0   0 1      
1 0 1 0 0 1 -
  1 0 1 1 0  
-------------------------------------
  1 0 0 1 1  

Se eseguendo una sottrazione diretta dobbiamo, per qualche bit, prendere il borrow dalle cifre che lo precedono, bisogna distinguere due casi:

la cifra immediatamente precedente è uno nel qual caso è sufficiente ricordare che la cifra da cui si prende il borrow, si riduce a zero e la cifra successiva aumenta di due (10 in binario);

la cifra (od alcune cifre) immediatamente precedente è zero, nel qual caso il borrow si prende dalla prima cifra non nulla, tutti gli zeri diventano uno ed infine il bit su cui si sta operando è aumentato di due (10 in binario).

COMPLEMENTO

1. CB [N] = BK - N C10 [24] = 102 - 24 = 76 C2 [100101] = 26 - 100101 = 011011

2.

    1 1 1 1 1 2  
  C2 [ 1 0 0 1 0 1 ] = 011011  
                 
    1 1 1 1 1 2  
  C2 [ 1 0 0 0 1 0 ] = 011110 CARRY!

3.

  100101 ® 011010 + complemento a 1
    1 =  
    ------------  
    011011 complemento a 2

4. Dato un numero N, per ottenere il suo complemento a due, si riscrivono i bit del numero stesso a partire da LSB lasciando inalterati tutti gli zeri fino a quando s'incontra il primo uno lo si ricopia e s'invertono i bit successivi (gli zeri in uno, gli uno in zero).

Per esempio, 100101 ® 011011.





Proposta di lavoro N°1

Costruire uno spread sheet che consenta di acquisire un valore intero decimale negativo e di fornirne il complemento a due, utilizzando la regola numero tre.

  A B

C

D E F G H I J K
1 VALORE INTERO

-16

               
2                    
3 Valore assoluto

16

               
4                    
5 Posto  

7

6

5

4

3

2

1

0

6                    
7 Configurazione binaria  

0

0

0

1

0

0

0

0

8                    
9 Complemento a uno  

1

1

1

0

1

1

1

1

10                    
11 Riporto  

0

0

0

1

1

1

1

1

12                    
13 Complemento a due  

1

1

1

1

0

0

0

0

Per il calcolo del valore assoluto relativo a C3 si potrà utilizzare la formula:

=ASS(C1)

Per il calcolo delle cifre binarie relative a C3, in ogni cella della riga 7 (ad esempio K7) si potrà utilizzare la formula:

=RESTO(INT($C$3/(POTENZA(2,K5)));2)

Per il calcolo del complemento a uno, si può ricorrere alla funzione di selezione:

=SE(K7=0;1;0)

Per il calcolo del complemento a due occorre poi sommare uno alla stringa trasformata, ciò può essere fatto riportando uno in K11 e poi facendo calcolare al PC la somma nella riga 13. In quest' operazione, dato che occorre tenere conto degli eventuali riporti, dalla colonna J fino alla colonna C della riga 11 saranno calcolati i riporti tramite la formula che, riferita alla colonna J assume la forma:

=INT((K9+K11)/2)

In modo analogo la formula per la riga 15 è:

=RESTO((K9+K11);2)

RISALIRE DAL COMPLEMENTO AL NUMERO

3.

  011011 -  
  1 =  
  ------------  
  011010 si sottrae 1
  100101 complemento a 1

4. 011011 ® 100101

La sottrazione di due numeri di k cifre può essere sostituita dall’addizione del minuendo al complemento del sottraendo (le cifre devono essere pareggiate a quelle del minuendo) purché nel risultato si trascuri il carry in posizione (k + 1).

Si noti che il metodo esposto è quello che in pratica è usato nei computer e l’eliminazione della cifra più significativa è eseguita in modo automatico dai circuiti elettronici.

DIVISIONE: è una sequenza di sottrazioni successive.

MOLTIPLICAZIONE: si riduce ad una serie di somme successive.

CONVERSIONE BINARIO-DECIMALE

Si rappresenta il numero binario in forma polinomiale e si sommano i valori decimali dei singoli termini del polinomio.

(10101.1011)2 = (21.6875)10

1*24 +0*23 +1*22 +0*21 +1*20 +1*2-1 +0*2-2 +1*2-3 +1*2-4 =16+4+1+0.5+0.125+0.0625

CONVERSIONE DECIMALE-BINARIO

Nel caso di numero intero si utilizza il metodo delle divisioni successive per la base B del sistema, il resto della divisione costituisce la cifra binaria, si procede così sul quoziente fino a quando quest’ultimo si annulla. Se il numero è frazionario si utilizza il metodo delle moltiplicazioni successive per la base B del sistema, la parte intera (zero o uno) rappresenta la cifra binaria, si procede così fino all’annullamento della parte frazionaria o fino a quando la precisione della conversione risulta sufficiente.

(316.5625)10 = (100111100.1001)2

316:2=158 0 ­ 0.5625*2=1.125 1 ½
158:2=79 0 ½ 0.125*2=0.25 0 ½
79:2=39 1 ½ 0.25*2=0.5 0 ½
39:2=19 1 ½ 0.5*2=1.0 1 ¯
19:2=9 1 ½      
9:2=4 1 ½      
4.2=2 0 ½      
2:2=1 0 ½      
1:2=0 1 ½      




SISTEMA OTTALE

Base: numero di simboli del sistema í 0, 1, 2, 3, 4, 5, 6, 7ý

è corretto leggere il numero ottale (574)8 come numero: cinque-sette-quattro e non cinquecentosettantaquattro poiché quest’ultima è una dicitura che caratterizza solo il sistema decimale.

ADDIZIONE

  1 1 1  
  4 2 1 6 +
    5 7 4
  ---------------------
  5 0 1 2

SOTTRAZIONE

    5   4       1 1   1    
  5 6 0 5 2 -       5 6 0 5 2 +
    4 2 4 5       7 3 5 3 3
----------------------------- -----------------------------
  5 1 6 0 5     1 5 1 6 0 5

CONVERSIONE OTTALE-DECIMALE

(24.12)8 = (20.15625)10

2*81+4*80+1*8-1+2*8-2 = 16+4+0.125+0.03125

CONVERSIONE DECIMALE-OTTALE

(4303.5625)10 = (10317.44)8

4303:8=537 7 ­ 0.5625*8=4.5 4 ½
537:8=67 1 ½ 0.5*8=4.0 4 ¯
67:8=8 3 ½      
8:8=1 0 ½      
1:8=0 1 ½      

CONVERSIONE BINARIO-OTTALE E VICEVERSA

Si suddivide il numero binario in gruppi di tre bit a partire dal punto binario, si completano con zero i gruppi estremi con meno di tre bit e si associa a ciascun gruppo il corrispondente ottale.

(1010.1101)2 = (12.64)8 ® (001) (010) · (110) (100)

DECIMALE OTTALE BINARIO
0 0 000
1 1 001
2 2 010
3 3 011
4 4 100
5 5 101
6 6 110
7 7 111



SISTEMA ESADECIMALE

Base: numero di simboli del sistema

í 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A (10), B (11), C (12), D (13), E (14), F (15)ý .

La CPU (Central Processing Unit) lavora con parole (word) binarie formate da un numero di bit multiplo del due, è facile rappresentarle in esadecimale.

BIT NOME CIFRE ESADECIMALI
4 nibble 1
8 byte 2
16 word 4
32 doubleword 8
64 quadword 16

ADDIZIONE

    1      
  E 0 1 A C +
      F 4 2
-------------------------
  E 1 0 E E

SOTTRAZIONE

    1   5     1 1   1    
  C 2 A 6 1 -     C 2 A 6 1 +
      B 0 E     F F 4 F 2
-------------------------- -----------------------------
  C 1 F 5 3   1 C 1 F 5 3

CONVERSIONE BINARIO-ESADECIMALE E VICEVERSA

Si suddivide il numero binario in gruppi di quattro bit a partire dal punto binario, si completano con zero i gruppi estremi con meno di quattro bit e si associa a ciascun gruppo il corrispondente esadecimale.

(1000101011101.1010)2 = (115D.A)H ® (0001) (0001) (0101) (1101) · (1010)

CONVERSIONE OTTALE-ESADECIMALE E VICEVERSA

Il metodo più veloce per passare dal sistema ottale all’esadecimale (o viceversa) è quello di passare attraverso il sistema binario.

(352)8 = (EA)H ® (352)8 = (11101010)2 = (EA)H

DECIMALE ESADECIMALE BINARIO
0 0 0000
1 1 0001
2 2 0010
3 3 0011
4 4 0100
5 5 0101
6 6 0110
7 7 0111
8 8 1000
9 9 1001
10 A 1010
11 B 1011
12 C 1100
13 D 1101
14 E 1110
15 F 1111

CONVERSIONE ESADECIMALE-DECIMALE

(8BA.3)H = (2234.18)10

8*162+B*161+A*160+3*16-1 = 2048+176+10+0.18

CONVERSIONE DECIMALE-ESADECIMALE

(8826.62)10 = (227A.9E)H

8826:16=551 10 ­ 0.62*16=9.92 9 ½
551:16=34 7 ½ 0.92*16=14.72 14 ¯
34:16=2 2 ½ 0.72*16=...    
2:16=0 2 ½      

Un modo più semplice e rapido per eseguire queste conversioni è quello di utilizzare un'opportuna tabella, per valori da (0)10 a (1048575)10; da (00000)H a (FFFFF)H.

Per convertire da esadecimale a decimale

Le colonne corrispondono al numero di cifre del valore esadecimale, le righe ai valori delle singole cifre esadecimali. Il valore (E)H ha una cifra ed il suo valore decimale è (colonna DIG. 1, riga E = 14). Il valore (E7)H ha due cifre ed il suo valore decimale è (colonna DIG. 2, riga E) + (colonna DIG. 1, riga 7) = (231)10. Il valore (E742)H ha quattro cifre ed il suo valore decimale è (colonna DIG. 4, riga E) + (colonna DIG. 3, riga 7) + (colonna DIG. 2, riga 4) + (colonna DIG. 1, riga 2) = (59202)10.

Per convertire da decimale ad esadecimale

Si trova il più vicino numero nella tabella, uguale o minore al numero decimale. La prima cifra del valore esadecimale è il numero nel lato sinistro della corrispondente riga (nella colonna ESAD). Si sottrae il valore della tabella dal numero originale e, si ripete il processo fino a quando il numero decimale è pari a zero.

Trovare il valore esadecimale di (1012342)10

Decimale Tabella Esadecimale

1012342 983040 = F

29302 28672 = 7

630 512 = 2

118 112 = 7

6 6 = 6

Pertanto (1012342)10 = (F7276)H

ESAD DIG. 5 DIG. 4 DIG. 3 DIG. 2 DIG. 1 BINARIO
0 0 0 0 0 0 0000
1 65536 4096 256 16 1 0001
2 131072 8192 512 32 2 0010
3 196608 12288 768 48 3 0011
4 262144 16384 1024 64 4 0100
5 327680 20480 1280’ 80 5 0101
6 393216 24576 1536 96 6 0110
7 458752 28672 1792 112 7 0111
8 524288 32768 2048 128 8 1000
9 589824 36864 2304 144 9 1001
A 655360 40960 2560 160 10 1010
B 720896 45056 2816 176 11 1011
C 786432 49152 3072 192 12 1100
D 851968 53248 3328 208 13 1101
E 917504 57344 3584 224 14 1110
F 983040 61440 3840 240 15 1111



Proposta di lavoro N°2

Realizzare un programma che, dato un numero binario in input, lo converta nel corrispondente numero decimale e viceversa.

/* Conversione da binario a decimale

bin è la sequenza dei bit del numero binario, i è il contatore di posizione nella sequenza bin

l è la lunghezza della sequenza bin, s è il valore di posizione dei bit nel numero

d è il valore del numero binario in decimale

i=0

if bin[i]!=0 then d=1

s=1

for i=1 to l

begin

s=s*2; if bin[i]!=0 then d=d+s

end

scrivi: Il numero in decimale è d. */

#include <stdio.h>

#include<string.h>

#include<stdlib.h>

#include <conio.h>

int main(void)

{ int bin[30];int i,l,d,s;char buff[20];

do { i=0; l=0; d=0;clrscr();

printf("\nPer terminare l'inserimento dei bit digitare il <.>\n\n");

do { printf ("Dammi il bit %d del numero in binario partendo dall'LSB: ",i); bin[i] = atoi (gets(buff));

if (strcmp(buff,"."));i++;

} while(strcmp(buff,"."));

l=i;i=0; if (bin[i]!=0) d=1;i++;s=1;

for(i=1;i<l;i++) { s*=2; if(bin[i]!=0) d+=s; }

printf ("\nIl numero in decimale è: %d",d); gotoxy(1,23);

puts("PREMERE ESC PER TERMINARE, UN TASTO QUALSIASI PER CONTINUARE ");

} while ( getch() !=0x1B);return (0);

}

/* Conversione da decimale a binario

n è il numero in decimale, bit è la sequenza dei bit ottenuti dalle divisioni successive di n

i è il contatore della sequenza bit

leggi n

i=1

while n>0

begin

if n%2 then bit[i]=1 else bit[i]=0; n=n/2; i=i+1

end

scrivi: Il numero in binario è bit. */

#include<stdio.h>

#include <conio.h>

int main(void)

{ int bit[30];int i,n;

do { i=0; n=0;clrscr();

printf ("\nDammi il numero in decimale: ");scanf ("%d",&n);

while(n>0) { if(n%2) bit[i]=1; else bit[i]=0; n /=2;i++; }

printf ("\nIl numero in binario è: "); while(i>0) { i--;printf ("%d",bit[i]); } gotoxy(1,23);

puts("PREMERE ESC PER TERMINARE, UN TASTO QUALSIASI PER CONTINUARE ");

} while ( getch() !=0x1B);return (0);

}

#include <stdio.h>

#include <conio.h>

void convnum (int number, char *buffer,int base, char *names[]);

int test[] = {1,3,7,15,31,63,127,255,511,0};

char *decsys[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"},

*octsys[] = {"0", "1", "2", "3", "4", "5", "6", "7"},

*binsys[] = {"0", "1"},

*hexsys[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};

int main (void)

{ int i;char buffer[25];clrscr(); printf ("\n\nDECIMALE:\n");i = 0;

do { convnum (test[i], buffer, 10, decsys);printf(" %s",buffer); } while (test[i++]);

printf("\n\nOTTALE:\n");i = 0;

do { convnum (test[i], buffer, 8, octsys);printf(" %s",buffer); } while (test[i++]);

printf("\n\nBINARIO:\n");i = 0;

do { convnum (test[i], buffer, 2, binsys);printf(" %s",buffer); } while (test[i++]);

printf("\n\nESADECIMALE:\n");i = 0;

do { convnum (test[i], buffer, 16, hexsys);printf(" %s",buffer); } while (test[i++]);getch();return (0);

}

void convnum (int number, char *buffer,int base, char *names[])

{ int basenum,nextpower,digit;char *c;

if (number < 0) { number = -number;*buffer++ = '-';} basenum = 1;

while ((nextpower = basenum * base) <= number) basenum = nextpower;

for (;basenum; basenum /= base)

{ digit = number / basenum;number -= digit * basenum; for (c = names [digit]; *c; c++) *buffer++ = *c;

} *buffer = '\0';

}

#include <stdio.h>

#include <string.h>

#include <ctype.h>

#include <limits.h>

#include <conio.h>

void StampaInBase (int base, long num, char *s), InputStringa (char *prompt, char *s);

int InputNumero (long *np);

enum { PREF2 = '%', PREF8 = '@', PREF16 = '$' }; enum { SUFF2 = 'b', SUFF8 = 'q', SUFF16 = 'h' };

const long maxnum = LONG_MAX/16-16; char digit[] = "0123456789abcdef";

/*LONG_MAX è una costante definita in <limits.h> che indica il massimo valore ammissibile per un long. Considerando la tecnica usata nella InputInt per la conversione in un valore numerico della stringa introdotta, maxnum è il massimo valore che, nel peggiore dei casi, non potrà dare overflow durante i calcoli. */

int main(void)

{ long n;

do { clrscr(); puts("\n **** CONVERSIONE DI BASE NUMERICA ****\n\n"

"I numeri possono essere dati in uno dei seguenti formati:\n\n"

" Decimale: nessun prefisso n‚ suffisso (es. 198)\n"

" Binario: prefisso % o suffisso b (es. %110, 110b)\n"

" Ottale : prefisso @ o suffisso q (es. @306, 306q)\n"

" Esadecimale: prefisso $ o suffisso h (es. $c6, c6h)");

InputNumero(&n);printf("\n ");StampaInBase(2,n,"(bin) = ");

StampaInBase(8,n,"(oct) = ");StampaInBase(10,n,"(dec) = "); StampaInBase(16,n,"(hex)\n");

} while (getch() !=0x1b); return (0);

}

/*InputNumero: accetta un numero in binario, ottale, decimale o esadecimale, mette il numero introdotto in *np, ritorna falso (0) se solo return.*/

int InputNumero(long *np)

{ char s[128];int ok,base,d,pref,suff;char *pi,*pf,*p;long pnum;

do { InputStringa("\nNumero positivo da convertire (ESC per smettere): ",s); if (*s == 0) { return(0); }

base = 10;pi = s;pf = s+strlen(s)-1;pref = tolower(*pi); if (pref == PREF2) base = 2;

else if (pref == PREF8) base = 8;else if (pref == PREF16) base = 16; if (base != 10) { pi++;}

else { suff = tolower(*pf); if (suff == SUFF2) base = 2; else if (suff == SUFF8) base = 8;

else if (suff == SUFF16) base = 16;if (base != 10) {pf--;} }

*np = 0; ok = 1;

while (ok && pi <= pf) { p = strchr(digit,tolower(*pi));

if (p == NULL || (d = p-digit) >= base) {

printf("\n- '%c' non è un digit valido in base %d.\n\n\a",*pi,base);ok = 0; }

else { if (*np >= maxnum) { puts("\n- Il numero è troppo grande per essere convertito.\a"); ok = 0;}

else { *np = (*np)*base+d;} } pi++; }

} while (!ok); return (1);

}

/*Dato che pi punta al primo carattere della stringa, esaminiamo se questo è un prefisso che indica una certa base. Bisogna controllare prima i prefissi dei suffissi, altrimenti un numero come $101b potrebbe essere considerato 101 binario (suffisso b) invece che 101b esadecimale (prefisso $). Solo se non ci sono prefissi, si può vedere se c'è un eventuale suffisso. In ogni caso, tolower converte in lettere minuscole (i numeri non cambiano) per cercare poi nella stringa globale digit[]. Il risultato finale andrà in *np, quindi operiamo direttamente su *np. Dovendo fare molte operazioni, sarebbe più efficiente definire una variabile provvisoria (es. n) ed assegnarne poi il risultato a *np alla fine dei calcoli. L'operazione di dereferencing, cioè accedere al valore puntato da un pointer (come *np), è infatti di solito molto più lenta di un accesso diretto al contenuto di una normale variabile (come n). */

void StampaInBase(int base, long num, char *s)

{ char buf[80];int i;

if (num == 0) { putchar(0); } else {i = 0; while (num > 0) {buf[i++] = digit[num%base];num /= base;}

while(i) { putchar(buf[--i]); } } printf("%s",s);

}

/*Le cifre non possono essere stampate direttamente perché‚ sono prodotte in ordine inverso. Le accumuliamo quindi in questa stringa, che verrà poi stampata a rovescio; num%base è il valore dell'ultimo digit a destra (ad esempio, nel caso di 235 in base 10, 235%10 vale 5). Questo valore viene usato come indice nella stringa digit[] per trovare il carattere corrispondente, che viene accumulato nella stringa buf[]; num viene aggiornato in modo da togliere il digit appena considerato (ad esempio, 235/10 vale 23). */

void InputStringa(char *prompt, char *s)

{ char buf[128];int ok;char *p;

do { printf(prompt);ok = (gets(buf) != NULL);if (! ok) putchar('\a'); } while (! ok); p = buf;

while (isspace(*p)) p++; while (*p && (! isspace(*p))) { *s++ = *p++; } *s = 0;

}

/*Si potrebbe leggere la stringa usando semplicemente la sscanf con "%s", ma abbiamo preferito mantenere lo spirito 'a basso livello' del programma, trattando anche le stringhe come i numeri. */