Come posso convertire un float/doppio in ASCII senza usare sprintf o ftoa in C?Come posso convertire un float/double in ASCII senza usare sprintf o ftoa in C?
Sto utilizzando un sistema incorporato.
Come posso convertire un float/doppio in ASCII senza usare sprintf o ftoa in C?Come posso convertire un float/double in ASCII senza usare sprintf o ftoa in C?
Sto utilizzando un sistema incorporato.
L'approccio scelto dipenderà dal possibile intervallo di valori. Sicuramente hai una conoscenza interna della gamma possibile e potresti essere interessato solo a conversioni in un intervallo più ristretto.
Quindi, supponiamo di essere interessato solo al valore intero. In questo caso, assegnerei il numero a int
o long
, a questo punto il problema diventa abbastanza ovvio.
Oppure, supponiamo che l'intervallo non includa esponenti di grandi dimensioni, ma sei interessato a più cifre di frazione. Per ottenere tre cifre di frazione, potrei dire int x = f * 1000;
, convertire x e quindi inserire il punto decimale come operazione stringa.
In caso contrario, un float o double ha un bit di segno, una frazione e un esponente. C'è un 1
nascosto nella frazione. (I numeri sono normalizzati fino a quando non hanno zero iniziali, a quel punto eseguono un ulteriore spostamento per ottenere un ulteriore bit di precisione.) Il numero è quindi uguale alla frazione (più un '1' iniziale) * 2 ** esponente . Con praticamente tutti i sistemi che utilizzano la rappresentazione IEEE 754, è sufficiente utilizzare this Wikipedia IEEE 754 page per comprendere il formato. Non è quello diverso dalla semplice conversione di un numero intero.
Per singola precisione, una volta a ottenere l'esponente e la frazione, il valore Nota 1 del numero è poi (frac/2 + 1) * 2 exp, o frac * 2 exp - 23 + 2 exp.
Ecco un esempio che dovrebbe iniziare in una conversione utile:
$ cat t.c
#include <stdio.h>
void xconvert(unsigned frac)
{
if (frac) {
xconvert(frac/10);
printf("%c", frac % 10 | '0');
}
}
void convert(unsigned i)
{
unsigned sign, exp, frac;
sign = i >> 31;
exp = (i >> (31 - 8)) - 127;
frac = i & 0x007fffff;
if (sign)
printf("-");
xconvert(frac);
printf(" * 2 ** %d + 2 ** %d\n", exp - 23, exp);
printf("\n");
}
int main(void)
{
union {
float f;
unsigned i;
} u;
u.f = 1.234e9;
convert(u.i);
return 0;
}
$ ./a.out
1252017 * 2 ** 7 + 2 ** 30
Nota 1. In questo caso la frazione viene convertito come se il punto binario era a destra, invece di sinistra, con regolazioni compensative fatte all'esponente e al bit nascosto.
Anche in un sistema embedded, si fatica a battere le prestazioni di ftoa. Perché reinventare la ruota?
'ftoa' potrebbe non essere effettivamente disponibile nelle librerie fornite. Dopo tutto, non fa parte della libreria standard e, anche se lo fosse, non è raro che i sistemi incorporati utilizzino implementazioni indipendenti che omettono gran parte della libreria standard. – jamesdlin
#include<stdio.h>
void flot(char* p, float x)
{
int n,i=0,k=0;
n=(int)x;
while(n>0)
{
x/=10;
n=(int)x;
i++;
}
*(p+i) = '.';
x *= 10;
n = (int)x;
x = x-n;
while(n>0)
{
if(k == i)
k++;
*(p+k)=48+n;
x *= 10;
n = (int)x;
x = x-n;
k++;
}
*(p+k) = '';
}
int main()
{
float x;
char a[20]={};
char* p=&a;
printf("Enter the float value.");
scanf("%f",&x);
flot(p,x);
printf("The value=%s",p);
getchar();
return 0;
}
Riscrivere 'ftoa'. – SLaks
Implementa te stesso 'ftoa'. Guarda l'implementazione in una libreria standard open source se hai bisogno di ispirazione. –
Hai accesso a "math.h"? –