AngoLinux

Analisi della rappresentazione interna di un float - Versione 2

- A cura del Prof. Stefano Salvi -


Una seconda versione della conversione. In questo caso si richiede la scrittura di una funzione generalizzata. Viene esplicitamente richiesto che si usi una funzione di converisone da binario a decimale che vada bene sia per la mantissa che per l'esponente.

Il testo dell'esercizio è il seguente:

Scrivere un programma C che legga da tastiera numeri in virgola mobile, float, e ne stampi la rappresentazione binaria.
Il programma dovrà continuare a chiedere numeri in virgola mobile e stampare i risultaiti, fino a chè l'utente non preme un certo testo.
Analizzare il formato del numero, eseguendo una serie di esperimenti e scrivere una serie di funzioni per stampare i valori componenti del numero.
Si utilizzi un'unica funzione con opportuni parametri per tutte le conversioni da binario a numero (usare un double anche per l'esponete, per generalità).
Note
  • Per analizzare un numero float occorre prima immagazzinarlo in un unsigned, che siamo in grado di converire. Per fare questo dobbiamo passare attraverso i puntatori e l'operazione di type cast. Dovremo:
    • Ottenere un puntatore al float con l'operatore &
    • Cambiare il tipo del puntatore tramite il type cast ad unsigned *
    • Ottenere il valore intero dell'immagine tramite l'operatore *
    L'operazione complessivamente potrebbe essere eseguita così : i = *(unsigned int *)&f;
  • Per convertire un numero a partire dal bit più significativo è possibile:
    1. utilizzare una variabile con il peso
    2. inizializzarla al peso del bit più significativo
    3. moltipolicare il peso per il bit corrente e sommarlo al numero convertito
    4. Dividere il peso per 2, per ottenere il peso del bit successivo
    5. Passare al bit successivo e ricominciare da 3 finchè ci sono bit

Una possibile soluzione è la seguente:
// Tizio - Pinco - 3AIN - 08/02/02 
// Rappresentazione binaria di un float

#include <stdio.h>

#define DIM 32		// Dimensione in bit di un float

void binario(unsigned b,int vett[],int dim);	// Prende il numero 'b' di 'dim' bit e lo
						// converte in 'vett'
void SegnMant(int vett[]);			// Visualiza il segno della mantissa
// Converte i bit in 'vet' da 'inizio' a 'fine' partendo dal peso massimo 'peso'
double conversione(double peso,int vet[],int inizio,int fine);
  
main()
{
double esp;		// Esponente convertito
double mant;		// Mantissa convertita
int vet[DIM];		// Vettore  nel quale immagazzinare il numero
unsigned i;		// Rappresentazione binaria del float
float f;		// Float letto
char m;			// Carattere per fine ciclo

  do{
    printf("\n\nNumero: "); scanf("%f",&f);	// Legge un float da tastiera
    if(f==0.000000)				// Se il float e' 0
    {
      printf(" 0.000000 * 2^ 000000");		// Stampa convenzionalemnte 0
    } else { 
      i = *(unsigned int *)&f;			// Trasferisce il float nell'unsigned
      binario(i,vet,DIM);			// Converte l'immagine in binario
      printf("\n");
      esp=conversione(128,vet,1,8);		// Converte esponente
      mant=conversione(1,vet,9,31);		// Converte mantissa
      esp=esp-128;				// Toglie offset ad esponente
      mant=mant+2;				// Aggiunge bit nascosto a mantissa
      SegnMant(vet);				// Stampa segno mantissa
      printf("%f ",mant);			// Stampa mantissa
      printf(" * 2^ %f",esp);			// tampa esponente
    }
    printf("\nEsc per terminare:\n");
    m=getchar();				// Pausa e ripetizione
  }while (m != 27);	// Finche' non si preme 'esc'
}

/* converte un intero in binario
 *
 * Converte l'intero 'b' di dimensione 'dim' bit nel vettore 'vett',
 * un bit per elemento, il bit piu' significativo nel primo elemento
 * Alla fine stampa il risultato della conversione
 */
void binario(unsigned int b, int vett[],int dim)
{
int j;   // Contatore per il ciclo
  for (j=0; j< dim; j++)  // memorizzazione a partire dall'ultimo
  {                       // elemento del vettore
    vett[dim-1-j]=b%2;   // resto della divisione
    b=b/2;               // quoziente della divisione
  }
  // Visualizzazione
  for(j=0;j<dim;j++)
  {
    printf("%d",vett[j]);
  }
}

/* visualizza il segno della mantissa
 *
 * Il segno della mantissa e' immagazzinato nel bit piu' significativo.
 * Il valore 0 indica segno positivo
 */
void SegnMant(int vett[])
{ 
  if(vett[0] == 0)
  {
    printf("+");
  } else {
    printf("-");
  }
}

/* Conversione binaria generica:
 * Converte il numero nel 'vettore di bit' 'vet', a partire dal bit vet[inizio]
 * fino al bit vet[fine] compreso.
 * Usa 'peso' come peso del bit piu' significativo.
 * Ritorna un double, in modo da convertire anche numeri in virgola fissa
 */
double conversione(double peso,int vet[],int inizio,int fine)
{
int i;		// Contatore dei bit
double c=0;	// Risutlato
  for(i=inizio;i<=fine;i++)	// Loop sui bit indicati	
  {
    c=c+peso*vet[i];	// Somma il bit corrente
    peso=peso/2;	// Aggiusta il peso per il prossimo
  }
  return c;		// Restituisce il risultato
}

Per provare il programma, scaricare il sorgente, compilarlo con il comando cc float2.c ed eseguirlo con il comando ./a.out.


[Home Page dell'ITIS "Fermi"] [Indice Terza] [Precedente] [Successivo]

© Ing. Stefano Salvi - Released under GPL licence