View Full Version : [C] convertire un numero reale positivo a binario
Ciao ragazii.Premetto che non sono esperto..Ho fatto un programmino che mi consente di convertire un numero intero a binario. Ma non riesco proprio a convertire un reale (con la virgola anche, e sta qui il problema) in binario.
Questo è il programmino da me fatto
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int reale;
int binario[32];
int i;
scanf("%d", &reale);
printf("hai digitato: ");
printf("il numero in binario vale: \n\n");
for (i=0; i<32; i++)
{
binario[32-1-i]=reale%2;
reale=reale/2;
}
for(i=0; i<32;i++)
{
printf("%d", binario[i]);
}
printf("\n\n");
system("PAUSE");
return 0;
}
Grazie in anticipo per chi sa darmi una mano
sottovento
10-05-2011, 12:34
Ciao ragazii.Premetto che non sono esperto..Ho fatto un programmino che mi consente di convertire un numero intero a binario. Ma non riesco proprio a convertire un reale (con la virgola anche, e sta qui il problema) in binario.
Questo è il programmino da me fatto
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int reale;
int binario[32];
int esadecimale[32];
int i;
scanf("%d", &reale);
printf("hai digitato: %d \n\n",reale);
printf("il numero in binario vale: \n\n");
for (i=0; i<32; i++)
{
binario[32-1-i]=reale%2;
reale=reale/2;
}
for (i = 0;i<32; i++)
{
esadecimale[32-1-i]=reale%16;
reale=reale/16;
}
for(i=0; i<32;i++)
{
printf("%d", binario[i]);
}
printf("\n\n");
system("PAUSE");
return 0;
}
Grazie in anticipo per chi sa darmi una mano
Devi prima di tutto leggere un reale, non un intero e dichiararlo, appunto, come reale.
Dopo di che, vorrei chiederti: che tipo di conversione reale->binario vuoi fare? Vuoi stampare mantissa & esponente? Ti vuoi limitare ad un esercizio e quindi stampare la parte intera a la parte decimale fino ad un certo numero di decimali dopo la virgola?
Il codice che hai scritto va bene per intero->binario; per il passaggio intero->esadecimale e' quasi ok. Va decisamente cambiato per reale->binario, ma prima devi chiarire la conversione che intendi implementare.
sulla dichiarazione del reale (float) ho capito.
In pratica voglio stampare un numero reale (positivo) anche con un certo numero di cifre decimali con la virgola.Con il metodo della mantissa ed esponente andrebbe bene, solo che non riesco a impostarlo.
Grazie ancora
sottovento
12-05-2011, 08:50
sulla dichiarazione del reale (float) ho capito.
In pratica voglio stampare un numero reale (positivo) anche con un certo numero di cifre decimali con la virgola.Con il metodo della mantissa ed esponente andrebbe bene, solo che non riesco a impostarlo.
Grazie ancora
Wow! Stampare mantissa ed esponente non e' semplicissimo. Ovviamente e' fattibile, ma se stai facendo un esercizio il mio consiglio e' di procedere per gradi e di provare prima a fare quello con un numero di cifre decimali prefissato.
Il concetto e' lo stesso che hai applicato nella applicazione che hai scritto: dopo la virgola, pero', invece che dividere il numero per due lo devi semplicemente moltiplicare. Il numero intero che ottieni (0 o 1) e' la tua cifra, la parte decimale rimanente la dovrai moltiplicare ancora per ottenere la cifra successiva.
Ovviamente, e' chiaro che numeri che in formato decimale NON sono periodici, lo potrebbero diventare una volta convertiti. Per questo di consiglio di fermarti ad un numero prefissato di cifre.
La conversione in binario mantissa+esponente e' un po' piu' articolata: devi "normalizzare" il numero (ci sono un paio di possibilita' diverse). Una volta fatto questo, puoi stampare l'esponente che hai ottenuto e la mantissa... ma prima, prova a fare la conversione con un numero fisso di decimali :D
Il concetto l'ho capito..O meglio so come ottenere la parte decimale.Pero' come devo dirgli di stampare su un'unica riga la parte decimale e intera insieme.
sottovento
14-05-2011, 20:33
Il concetto l'ho capito..O meglio so come ottenere la parte decimale.Pero' come devo dirgli di stampare su un'unica riga la parte decimale e intera insieme.
Beh, quello e' piuttosto semplice. Nel codice che hai scritto e postato all'inizio, usavi la printf(). Potresti usare ancora la printf(), o piu' printf() di seguito, evitando di andare a capo (i.e. il carattere "\n") finche' non hai finito.
Ho il dubbio che non sia quello che volevi chiedere :D Ad ogni modo, quando hai scritto il codice per decodificare il numero decimale con un numero fisso di decimali, puoi pubblicarlo e con poche modifiche si puo' ottenere la decodifica mantissa + esponente.
Io ho fatto esattamente la stessa cosa per gestire una comunicazione seriale.
Devi procedere per gradi:
1) Determinare se il tuo numero è positivo o negativo in modo da sapere se il bit 31 sarà 1 o 0.
2) Costruirti la mantissa (questa è la parte difficile.. ti consiglio di iterare una divisione per due e tenere traccia delle iterazioni fatte) fino a che non hai un numero inferiore a due.
3) Costruirti l'esponente (tenendo conto della notazione E128).
A questo punto concatena i bit in una variabile unsigned int o simile a 32 bit utilizzando espressioni di & e | e.... buon divertimento!
Per qualche notizia sulla virgola mobile, ecco un link..http://en.wikipedia.org/wiki/IEEE_754
niente da fare...ho fatto un pasticcio..Ho cercato di seguire i vostri consigli ma per me è abbastanza difficile...!!!
sottovento
17-05-2011, 21:38
niente da fare...ho fatto un pasticcio..Ho cercato di seguire i vostri consigli ma per me è abbastanza difficile...!!!
Dai, non buttarti giu'. Sono sicurissimo che non sei molto lontano dalla soluzione. Se posti il codice ci diamo un'occhiata, se vuoi.
Hai provato, prima di tutto, a fare la conversione con un numero FISSO di decimali? Si tratta di moltiplicare per due invece di dividere...
Si la conversione del numero fisso riesco a farla con la moltiplicazione..Ma il metodo della mantissa e dell'esponente non so proprio come fare.Il fatto è che la teoria la so bene.
Io voglio usare un float positivo che puo' essere un numero a caso come 12.15 ad esempio (la condizione della positivita' devo dichiararla in caso nel while) e convertirlo in sto benedetto numero binario.Come so il float non prende l'operatore % (modulo),quindi devo fare il metodo della mantissa ed esponente. Voglio usare 32 bit. Con questo metodo
1 bit per il segno (ma è sempre positivo)
8 bit per l'esponente
23 bit per la mantissa
Ecco non so come tradurre cio' nel linguaccio c..Lo so che non è poco ma vorrei sapere se è possibile come modificare il programmino iniziale che ho pubblicato.
Grazie in anticipo
sottovento
18-05-2011, 09:40
Si la conversione del numero fisso riesco a farla con la moltiplicazione..Ma il metodo della mantissa e dell'esponente non so proprio come fare.Il fatto è che la teoria la so bene.
Io voglio usare un float positivo che puo' essere un numero a caso come 12.15 ad esempio (la condizione della positivita' devo dichiararla in caso nel while) e convertirlo in sto benedetto numero binario.Come so il float non prende l'operatore % (modulo),quindi devo fare il metodo della mantissa ed esponente. Voglio usare 32 bit. Con questo metodo
1 bit per il segno (ma è sempre positivo)
8 bit per l'esponente
23 bit per la mantissa
Ecco non so come tradurre cio' nel linguaccio c..Lo so che non è poco ma vorrei sapere se è possibile come modificare il programmino iniziale che ho pubblicato.
Grazie in anticipo
Sei a buon punto! Quando hai tradotto il tuo numero 12.15, avrai qualcosa del tipo
00001100.0001001 (e cosi' via, se non sbaglio e' periodico. NOTA - ho fatto la conversione "al volo", non fidarti :D).
Conosci quindi gia' il segno: 0 (cioe' positivo, avrai la mantissa positiva).
Ora, dividi questo numero per 2 fino a scriverlo nella forma 1.xxxx, cioe' conta quante volte devi spostare il punto decimale a sinistra:
1.1000001001 x 2^3
voila'. Praticamente hai finito. 3 e' il tuo esponente e la parte a destra del punto decimale e' la tua mantissa.
Lo standard IEEE 754 pero' non vuole che si scriva 3 come esponente (ci sono delle buone ragioni) ma esige che si aggiunga 127, per cui se vuoi rispettare suddetta condizione, l'esponente sara' 130.
Giustapponi il segno, l'esponente (8 bit) e la mantissa (23 bit pero', io mi sono fermato prima perche' sono limitato) ed avrai il tuo numero.
Come vedi, hai gia' fatto la parte difficile.
Al limite, se vuoi conferma, puoi sempre fare un programmino che ti aiuti, chiedendo al calcolatore l'effettiva codifica:
float f = (float)12.15;
unsigned int *p = (unsigned int *)&f;
printf ("%f codificato in 0x%04x\n", f, *p);
Ti stampera' la tua codifica. Per prima cosa, prova a dare un'occhiata a questa, dopo immagino sara' piu' facile scrivere la parte di software che ti manca
niente da fare.Non riesco a farlo.Potresti postarmi i passaggi dove modificare il mio programmino iniziale? Sempre se non chiedo troppo..!!
sottovento
19-05-2011, 09:02
niente da fare.Non riesco a farlo.Potresti postarmi i passaggi dove modificare il mio programmino iniziale? Sempre se non chiedo troppo..!!
No, non chiedi troppo, se non che, come tutti, ho poco tempo per postare una soluzione vera.
Questo e' cio' che ho pensato. E' adatto piu' a spiegare che ad essere impiegato in un programma "vero". Spero mi perdonerai per questo
NOTA - ti accorgerai che ci sono delle idiosincrasie, per esempio nelle dichiarazioni delle costanti. Potresti pensare come scrivere un programma vero. Inoltre occorre testare dei casi che per mancanza di tempo non ho fatto: numeri < 1 e negativi
Ah! Ultima cosa: la dichiarazione delle variabili segue il C++, non il C perche' sono pigro. Beh, non e' un grosso problema, no? :D
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MANTISSA_LENGTH 23
#define EXP_LENGTH 8
void converti_parte_intera (int parte_intera, char *intera_bin, int length)
{
intera_bin[length-1] = '\0';
for (int i = length-2; i >= 0; i--)
{
intera_bin[i] = (parte_intera % 2) + '0';
parte_intera /= 2;
}
}
void converti_parte_decimale (float num, char *dec_bin, int length)
{
for (int i = 0; i < length-1; i++)
{
num *= (float)2.0;
if (num >= (float)1.0)
{
num -= (float)1.0;
dec_bin[i] = '1';
}
else
dec_bin[i] = '0';
}
dec_bin[length-1] = '\0';
}
int calcolaEsponente(int parte_intera, float parte_decimale)
{
int count = 0;
if (parte_intera > 0)
{
while (parte_intera > 0)
{
parte_intera /= 2;
count++;
}
// Arrivati qui, la parte intera e' <= 0, quindi devo ritornare il contatore -1
return count-1;
}
else
{
while ((parte_decimale > (float)0.0) && count < 32)
{
parte_decimale *= (float)2.0;
count++;
}
if (count == 32)
return 0;
else
return -1 * (count - 1);
}
}
void traduci (float num, int &segno, char *mantissa, char *esponente)
{
char int_bin[33];
char dec_bin[33];
if (num < (float)0.0)
{
segno = -1;
num *= (float)-1.0;
}
else
segno = 0;
printf ("Numero: %f\n", num);
int parte_intera = (int)num;
converti_parte_intera (parte_intera, int_bin, 33);
printf ("Parte intera: %s\n", int_bin);
num -= (float)parte_intera;
converti_parte_decimale (num, dec_bin, 33);
printf ("Parte decimale: %s\n", dec_bin);
// Giustapponendo le due parti, ho la rappresentazione del numero con esponente 2^0, ovviamente
// Calcolo l'esponente.
int esp = calcolaEsponente(parte_intera, num); // Guardo la parte intera se > 0; altrimenti guardo la parte decimale
printf ("esponente: %d\n", esp);
// L'esponente e' pari al numero di shift che devo fare per ottenere la mantissa:
// - se > 0, devo shiftare il punto decimale verso sinistra;
// - se < 0, devo shiftare il punto decimale verso destra;
int _esp = esp + 127;
if (esp > 0)
{
// prendo gli ultimi "esp" elementi dalla parte intera, ed il resto dalla parte decimale
memcpy (mantissa, &int_bin[32 - esp], esp);
memcpy (&mantissa[esp], dec_bin, MANTISSA_LENGTH - esp);
mantissa[MANTISSA_LENGTH] = '\0';
}
else
{
esp = -esp;
memset(mantissa, '0', MANTISSA_LENGTH);
memcpy(mantissa, &dec_bin[esp], MANTISSA_LENGTH - esp);
mantissa[MANTISSA_LENGTH] = '\0';
}
converti_parte_intera (_esp, esponente, EXP_LENGTH+1);
}
int main(int argc, char *argv[])
{
float num = (float)12.95;
int segno;
char mantissa[MANTISSA_LENGTH+1];
char esponente[EXP_LENGTH+1];
traduci (num, segno, mantissa, esponente);
printf ("segno: %d\n", segno);
printf ("mantissa: %s\n", mantissa);
printf ("esponente: %s\n", esponente);
printf ("Il numero %f tradotto in IEEE754 e' percio' %d%s%s\n", num, segno, esponente, mantissa);
unsigned int *p = (unsigned int *)#
printf ("VERIFICA: lo stesso numero, cosi' come memorizzato nel computer e' 0x%x\n", *p);
return 0;
}
No figurati per le variabili di c++..Il problema è mio che dico delle cose un po' per volta e di conseguenza gli faccio perdere tempo.Mi ero dimenticato a dirle che l'uso di funzioni non è consentito nell'esercizio che devo fare...!!!
sottovento
19-05-2011, 13:52
No figurati per le variabili di c++..Il problema è mio che dico delle cose un po' per volta e di conseguenza gli faccio perdere tempo.Mi ero dimenticato a dirle che l'uso di funzioni non è consentito nell'esercizio che devo fare...!!!
Se mi da del lei, rispondo a modo :D
Beh, non sapevo fosse un esercizio. Non sono molto d'accordo con tutte le regole di questo forum ma sono cmq tenuto a rispettarle. Non si possono fornire le soluzioni degli esercizi, solo aiuti.
Ad ogni modo, non e' difficile rimuovere le funzioni, soprattutto in questo caso. Si tratta di sostituire del testo ed aggiornare i nomi delle variabili
ok....provo a modificare il testo e a postarlo..!!
vediamo che combino
Allora ho fatto con un mio amico questo programmino in c prendendo spunto un po dal tuo.Il fatto è che non so come togliere le funzioni anche da questo.Potresti darmi qualche indicazione?
#include <stdio.h>
#define DIM 32
void binario(unsigned b,int vett[],int dim);
void SegnMant(int vett[]);
void mantissa(int vett[]);
void esponente(int vett[]);
main()
{
int vet[DIM];
unsigned i;
float f;
char m;
do{
printf("\n\nNumero: "); scanf("%f",&f);
if(f==0.000000)
{
printf(" 0.000000 * 2^ 000000");
} else {
i = *(unsigned int *)&f;
binario(i,vet,DIM);
printf("\n");
SegnMant(vet);
mantissa(vet);
esponente(vet);
}
printf("\nEsc per terminare:\n");
m=getchar();
}while (m != 27);
}
void binario(unsigned int b, int vett[],int dim)
{
int j;
for (j=0; j< dim; j++)
{
vett[dim-1-j]=b%2;
b=b/2;
}
for(j=0;j<dim;j++)
{
printf("%d",vett[j]);
}
}
void SegnMant(int vett[])
{
if(vett[0] == 0)
{
printf("+");
} else {
printf("-");
}
}
void mantissa(int vett[])
{
int i=0;
float peso=1;
float dec=2;
for(i=9;i<DIM;i++)
{
dec=dec+vett[i]*peso;
peso=peso/2;
}
printf("%f",dec);
}
void esponente(int vett[])
{
int i;
int p=128;
int esp=0;
for(i=1;i<=8;i++)
{
esp=esp+vett[i]*p;
p=p/2;
}
esp-=128;
printf(" * 2^ %d\n",esp);
system("PAUSE");
}
sottovento
20-05-2011, 07:59
Allora ho fatto con un mio amico questo programmino in c prendendo spunto un po dal tuo.Il fatto è che non so come togliere le funzioni anche da questo.Potresti darmi qualche indicazione?
}
Prova a fare la sostituzione, facendo attenzione ai parametri.
Per esempio, nel tuo codice c'e' scritto:
} else {
i = *(unsigned int *)&f;
binario(i,vet,DIM);
printf("\n");
SegnMant(vet);
mantissa(vet);
esponente(vet);
}
printf("\nEsc per terminare:\n");
m=getchar();
}while (m != 27);
Volendo sostituire SegnMant(vet), rimpiazzerai suddetta istruzione con il codice ivi contenuto, ed otterrai:
} else {
i = *(unsigned int *)&f;
binario(i,vet,DIM);
printf("\n");
if(vett[0] == 0)
{
printf("+");
} else {
printf("-");
}
mantissa(vet);
esponente(vet);
}
printf("\nEsc per terminare:\n");
m=getchar();
}while (m != 27);
Facile, no?
Attenzione - non ho controllato il tuo programma ma c'e' qualcosa di un po' strano. Per esempio:
if(f==0.000000)
{
printf(" 0.000000 * 2^ 000000");
}
Non si puo' sperare che questa uguaglianza venga verificata.
void mantissa(int vett[])
{
int i=0;
float peso=1;
float dec=2;
for(i=9;i<DIM;i++)
{
dec=dec+vett[i]*peso;
peso=peso/2;
}
printf("%f",dec);
}
Non sono sicuro che calcoli la mantissa, in particolare non capisco perche' inizializzi dec a 2 (otterrai quindi un numero >= 2).
void esponente(int vett[])
{
int i;
int p=128;
int esp=0;
for(i=1;i<=8;i++)
{
esp=esp+vett[i]*p;
p=p/2;
}
esp-=128;
printf(" * 2^ %d\n",esp);
system("PAUSE");
}
Da quello che mi ricordo di IEEE754 dovresti sottrarre 127 dal calcolo finale, non 128. Posso anche ricordarmi male, ma ho visto gli appunti di Morzenti del Politecnico di Milano ed anche lui usa 127.
Ho modificat un po' come mi ha detto lei..Ma non mi funziona..!
Ho messo tutte le variabili all'inizio e poi ho fatto il resto togliendo le funzioni..!!
#include <stdio.h>
#define DIM 32
main()
{
int vett[DIM];
float f;
char m;
int i=0;
float peso=1;
float dec=2;
int b;
int p=128;
int esp=0;
int j;
do{
printf("\n\nNumero: ");
scanf("%f",&f);
if(f==0.000000)
{
printf(" 0.000000 * 2^ 000000");
}
else {
for (j=0; j< DIM; j++)
{
vett[DIM-1-j]=b%2;
b=b/2;
}
for(j=0;j<DIM;j++)
{
printf("%d",vett[j]);
}
if(vett[0] == 0)
{
printf("+");
} else {
printf("-");
}
for(i=9;i<DIM;i++)
{
dec=dec+vett[i]*peso;
peso=peso/2;
}
printf("%f",dec);
}
for(i=1;i<=8;i++)
{
esp=esp+vett[i]*p;
p=p/2;
}
esp-=128;
printf(" * 2^ %d\n",esp);
printf("\nEsc per terminare:\n");
m=getchar();
}while (m != 27);
system("PAUSE");
}
sottovento
23-05-2011, 10:03
Alcune osservazioni:
if(f==0.000000)
{
printf(" 0.000000 * 2^ 000000");
}
Come dicevo, questo confronto non ha senso per quanto riguarda i numeri reali!
for (j=0; j< DIM; j++)
{
vett[DIM-1-j]=b%2;
b=b/2;
}
Stai usando la variabile b a cui non e' mai stato assegnato alcun valore! Se non assegni un valore, il contenuto di b sara' casuale, pertanto il vettore vett sara' riempito anche lui di cifre binarie casuali.
for(i=9;i<DIM;i++)
{
dec=dec+vett[i]*peso;
peso=peso/2;
}
Ha inizializzato peso ad 1 e dec a 2. Ammesso che vett sia corretto, non otterrai la mantissa poiche' il bit piu' significativo della mantissa deve aver peso 0.5.
Se ho capito quel che vuoi fare, inizializzerei dec a 0 e peso a 0.5. Dopo di che, una volta completato questo ciclo, aggiungerei 1 al risultato.
esp-=128;
Nel sistema IEEE754 e' 127, non 128.
Suggerimento: uno step alla volta. Assicurati che vett contenga il valore corretto e non andare avanti fintanto che non hai risolto questo punto
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.