c++ - svolti - virgola mobile spiegazione




Analizza la virgola mobile IEEE a doppia precisione su un compilatore C senza doppio tipo di precisione (3)

C'è una sola implementazione completa del doppio IEEE754 in GCC per AVR di cui sono a conoscenza, e puoi trovarlo here .

Avrai bisogno di this archivio e quindi sostituirai avr_f64.c dall'archivio con this .

La libreria richiede circa 21K Flash e 310 byte di RAM.

Il post originale può essere trovato here . Ho estratto tutte le informazioni importanti dal post originale e presentato qui poiché penso che sia necessario disporre di un account per accedere al forum.

Sto lavorando con un chip AVR a 8 bit. Non esiste un tipo di dati per un doppio a 64 bit (doppio solo mappe per il float a 32 bit). Tuttavia, riceverò il doppio a 64 bit su seriale e dovrò emettere doppio a 64 bit su seriale.

Come posso convertire il doppio a 64 bit in un float a 32 bit e viceversa senza eseguire il cast? Il formato per entrambi i 32 bit e 64 bit seguirà IEEE 754. Naturalmente, presumo una perdita di precisione durante la conversione al float a 32 bit.

Per la conversione da float 64-bit a 32-bit, sto provando questo:

// Script originally from http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1281990303
float convert(uint8_t *in) {
  union {
    float real;
    uint8_t base[4];
  } u;
  uint16_t expd = ((in[7] & 127) << 4) + ((in[6] & 240) >> 4);
  uint16_t expf = expd ? (expd - 1024) + 128 : 0;
  u.base[3] = (in[7] & 128) + (expf >> 1);
  u.base[2] = ((expf & 1) << 7) + ((in[6] & 15) << 3) + ((in[5] & 0xe0) >> 5);
  u.base[1] = ((in[5] & 0x1f) << 3) + ((in[4] & 0xe0) >> 5);
  u.base[0] = ((in[4] & 0x1f) << 3) + ((in[3] & 0xe0) >> 5);
  return u.real;
}

Per numeri come 1.0 e 2.0, quanto sopra funziona, ma quando ho provato a passare in una versione 1.1 come una doppia a 64 bit, l'output era un po 'scadente (letteralmente, non un gioco di parole!), Anche se questo potrebbe essere un problema con il mio test. Vedere:

// Comparison of bits for a float in Java and the bits for a float in C after
// converted from a 64-bit double. Last bit is different.
// Java code can be found at https://gist.github.com/912636
JAVA FLOAT:        00111111 10001100 11001100 11001101
C CONVERTED FLOAT: 00111111 10001100 11001100 11001100

IEEE specifica cinque diverse modalità di arrotondamento , ma quella da utilizzare per impostazione predefinita è Da metà a pari . Quindi hai una mantissa del formato 10001100 11001100 11001100 11001100 ... e devi arrotondarla a 24 bit. Numerando i bit da 0 (il più significativo), il bit 24 è 1; ma questo non è abbastanza per dirti se arrotondare o no il bit 23. Se tutti i bit rimanenti erano 0, non si arrotolerebbe, perché il bit 23 è 0 (pari). Ma i bit rimanenti non sono zero, quindi arrotondi in tutti i casi.

Qualche esempio:

10001100 11001100 11001100 10000000 ... (tutto zero) non viene arrotondato, poiché il bit 23 è già uniforme.

10001100 11001100 11001101 10000000 ... (tutto zero) si arrotonda, poiché il bit 23 è dispari.

10001100 11001100 1100110x 10000000 ... 0001 arrotonda sempre, poiché i bit rimanenti non sono tutti zero.

10001100 11001100 1100110x 0xxxxxxx ... non si arrotonda mai, poiché il bit 24 è zero.






avr