Converti double/float in stringa

Converti double/float in stringa


Ho bisogno di convertire un numero in virgola mobile in una stringa equivalente in decimale (o altra base). La conversione all'inizio deve essere eseguita nel formato xE+0 dove x è il numero in virgola mobile.


L'idea che ho è di troncare prima il numero in virgola mobile in un numero intero temporaneo e quindi convertire quel numero intero in stringa, quindi considerare la parte frazionaria, moltiplicarla per 10 mentre la parte frazionaria non diventa 0 . Dopo che la parte frazionaria è stata trasferita nel lato sinistro della virgola decimale, applicare nuovamente l'intero alla funzione stringa e convertire la parte frazionaria in stringa. C'è un modo migliore, che sarà più veloce di questo? Questo metodo indurrà qualsiasi tipo di effetto collaterale?


Per convertire il numero in virgola mobile in una rappresentazione esponenziale, devo fare come sopra e quindi regolare la potenza? Oppure maschera direttamente la rappresentazione in virgola mobile IEEE 754 e converti ogni parte in una stringa.


Nota:non è stato possibile utilizzare altre funzioni, perché non ho assolutamente accesso a nessuna funzione di libreria. Questo codice va in un kernel giocattolo.


Risposte:


L'unica soluzione esatta è eseguire aritmetica decimale di precisione arbitraria per la conversione di base, poiché il valore esatto può essere molto lungo - per long double a 80 bit , fino a circa 10000 cifre decimali. Fortunatamente è "solo" fino a circa 700 posti per IEEE double .


Invece di lavorare con singole cifre decimali, è utile invece lavorare in base 1 miliardo (la potenza massima di 10 che rientra in un intero a 32 bit) e quindi convertire queste "cifre in base 1 miliardo" in 9 cifre decimali ciascuna alla fine del tuo calcolo.


Ho un'implementazione molto densa (piuttosto difficile da leggere) ma efficiente qui, sotto LGPL Licenza MIT:


http://git.musl-libc.org/cgit/musl/blob/src/stdio/vfprintf.c?h=v1.1.6


Se elimini tutto il supporto float esadecimale, il supporto infinity/nan, %g /%f /%e supporto per variazioni, arrotondamenti (che non saranno mai necessari se desideri solo risposte esatte) e altre cose di cui potresti non aver bisogno, il codice rimanente è piuttosto semplice.