PDA

View Full Version : [C] Rappresentazione di un float


k_mishima
30-04-2007, 21:41
Ciao, devo fare questo esercizio sempre sulle rappresentazioni di numeri :muro:

Non riesco a far visualizzare correttamente la mantissa, e non capisco dove ho sbagliato

La traccia dell'esercizio sta a inizio codice

/* Scrivere una function per la rappresentazione di un numero float (s,e,m) */

#include <stdio.h>
void FLOAT (float x, short *segno, short *esponente, int mantissa[23]);
void dec2bin(unsigned int inp, char binstr[8]);
main()
{

short segno,esponente,i;
int mantissa[23];
char esponente_b[8];
float x;
puts("Un float e' rappresentato da 32 bit cosi' divisi secondo lo standard IEEE 754");
puts("1 bit per il segno");
puts("8 bit per l'esponente");
puts("23 bit per la mantissa\n");

puts("Il bit segno e' 0 se il numero e' positivo, 1 se e' negativo");
puts("L'esponente si rappresenta come un BIASED quindi vale da 0 a 255\n");
puts("Ricordarsi che un bit della mantissa e' implicito e che qui i\nnumeri sono normalizzati");
puts("Digita il numero da rappresentare: ");
scanf("%f",&x);
FLOAT(x,&segno,&esponente,mantissa);

dec2bin(esponente,esponente_b);

printf("\nSEGNO: %hd\n",segno);
printf("ESPONENTE: ");
for (i=0;i<8;i++)
printf("%c",esponente_b[i]);
printf("\nMANTISSA: ");
for (i=22;i>=0;i++)
printf("%d",mantissa[i]);
printf("\n");
system("pause");


}

void FLOAT (float x, short *segno, short *esponente, int mantissa[23])
{
short i,BIAS=127;
*esponente=0;

if (x>=0)
*segno=0;
else
*segno=1;

while (((int)x>1))
{
mantissa[22-*esponente]=(int)x%2;
x/=2;
*esponente+=1;
}

for (i=22-(*esponente);i>=0;i--)
mantissa[i]=0;
*esponente+=BIAS;
}

void dec2bin(unsigned int inp, char binstr[8])
{
int i;
for (i = 0; i < 8; i++, inp >>= 1)
binstr[7-i] = (inp & 1) + '0';
}


Qualcuno sa' dove ho sbagliato? Tnx

andbin
30-04-2007, 22:11
Ciao, devo fare questo esercizio sempre sulle rappresentazioni di numeri :muro:

Non riesco a far visualizzare correttamente la mantissa, e non capisco dove ho sbagliatoSeguendo le specifiche IEEE 754 (http://en.wikipedia.org/wiki/IEEE_754), per estrarre le tre parti si potrebbe fare una cosa del genere (non testato!):
float val = 1.234f;

int fbits, segno, esponente, mantissa;

fbits = *((int*) &val);

segno = (fbits >> 31) & 1;
esponente = (fbits >> 23) & 0xFF;
mantissa = fbits & 0x7FFFFF;

k_mishima
01-05-2007, 15:54
Appena testato, funziona perfettamente grazie (sul mio poi mi sono accorto che avevo sbagliato un i++ nella stampa, ma cmq funzionava solo con i numeri positivi e interi) :rolleyes:


Mi spiegheresti questa riga?
fbits = *((int*) &val);

poi 0xFF è 8 '1', 0x7FFFFF è 23 '1' consecutivi vero?

Ogni F sono 4 bit '1' perchè vale 16, mentre il 7 sono 3 bit '1'.

Non sono pratico della notazione esadecimale, perchè si scrive 0x(valori) ?

Cmq effettivamente è molto comoda questa notazione, altrimenti in decimale avresti dovuto mettere 2^23 che non è un numero piccolo.

Grazie

andbin
01-05-2007, 19:29
Mi spiegheresti questa riga?
fbits = *((int*) &val);È il "fulcro" di tutta la estrazione ....

Sui tipi di dati floating-point (float o double che sia) non si possono eseguire operazioni con gli operatori bitwise (AND, OR, ecc....) e nemmeno usare gli operatori di shift.
E per esaminare i singoli bit non ha nemmeno senso fare un cast a int, ad esempio. Perché così faresti solamente una mera conversione a valore intero, che tronca i decimali e che quindi causa una perdita di precisione/magnitudo del valore originale.

Quindi supponendo che un float abbia la stessa dimensione di un int (cioè 32 bit) si può fare in modo da avere nel valore int gli stessi bit che compongono il float.

&val ..... denota l'indirizzo di val, come tipo è un float*
(int*) &val ..... fa un cast da float* a int*
*((int*) &val) ..... il puntatore a int viene dereferenziato, i 4 byte che compongono il float vengono "visti" come componenti di un int, quindi appunto prelevati e messi in fbits.

poi 0xFF è 8 '1', 0x7FFFFF è 23 '1' consecutivi vero?Sì

Ogni F sono 4 bit '1' perchè vale 16, mentre il 7 sono 3 bit '1'.0xF vale 15

Non sono pratico della notazione esadecimale, perchè si scrive 0x(valori) ?Perché questa è la sintassi richiesta dal "C" come anche da molti altri linguaggi (Java, C#, PHP ecc...).

Cmq effettivamente è molto comoda questa notazione, altrimenti in decimale avresti dovuto mettere 2^23 che non è un numero piccolo.2^23 in hex è 0x800000, non vedo cosa centra con i valori menzionati sopra.

k_mishima
03-05-2007, 16:11
È il "fulcro" di tutta la estrazione ....

Sui tipi di dati floating-point (float o double che sia) non si possono eseguire operazioni con gli operatori bitwise (AND, OR, ecc....) e nemmeno usare gli operatori di shift.
E per esaminare i singoli bit non ha nemmeno senso fare un cast a int, ad esempio. Perché così faresti solamente una mera conversione a valore intero, che tronca i decimali e che quindi causa una perdita di precisione/magnitudo del valore originale.

Quindi supponendo che un float abbia la stessa dimensione di un int (cioè 32 bit) si può fare in modo da avere nel valore int gli stessi bit che compongono il float.

&val ..... denota l'indirizzo di val, come tipo è un float*
(int*) &val ..... fa un cast da float* a int*
*((int*) &val) ..... il puntatore a int viene dereferenziato, i 4 byte che compongono il float vengono "visti" come componenti di un int, quindi appunto prelevati e messi in fbits.


Ah ok, ora mi è chiaro.


2^23 in hex è 0x800000, non vedo cosa centra con i valori menzionati sopra.

intendevo 2^23 meno 1, mi sono dimenticato il meno 1

Cmq grazie mille, i tuoi consigli sono preziosi :)

andbin
03-05-2007, 16:23
ntendevo 2^23 meno 1, mi sono dimenticato il meno 1Ah, ok. In C si può scrivere: (1<<23)-1