convertir - string to float c++
Convertir doble/flotar a cadena (7)
Necesito convertir un número de punto flotante en una cadena equivalente en decimal (u otra base). La conversión al principio debe realizarse en el formato xE+0
donde x
es el número de punto flotante.
La idea que tengo es primero truncar el número de punto flotante en un entero temporal y luego convertir ese entero en una cadena, y luego considerar la parte fraccionaria, multiplicarla por 10
mientras que la parte fraccionaria no se convierte en 0
. Después de que la parte fraccionaria se transfiera al lado izquierdo del punto decimal, aplique nuevamente el número entero a la función de cadena y convierta la parte de fracción en cadena. ¿Hay alguna forma mejor, que sea más rápida que esta? ¿Este método inducirá algún tipo de efectos secundarios?
Para convertir el número de punto flotante en representación exponencial, ¿haré lo mismo que arriba y luego ajustaré la potencia? O directamente enmascara la representación de punto flotante IEEE 754 y convierte cada parte en una cadena.
Nota: No se pueden usar otras funciones, porque no tengo acceso a ninguna función de biblioteca. Este código entra en un kernel de juguete.
La única solución exacta es realizar una aritmética decimal de precisión arbitraria para la conversión base, ya que el valor exacto puede ser muy largo: para el long double
80 bits de long double
, hasta aproximadamente 10000 lugares decimales. Afortunadamente, es "solo" hasta aproximadamente 700 lugares para el double
IEEE.
En lugar de trabajar con dígitos decimales individuales, es útil trabajar base-1-billón (la potencia más alta de 10 que cabe en un entero de 32 bits) y luego convertir estos "dígitos de base-billón" a 9 dígitos decimales cada uno al final de su computación.
Tengo una implementación muy densa (bastante difícil de leer) pero eficiente aquí, bajo licencia LGPL MIT:
http://git.musl-libc.org/cgit/musl/blob/src/stdio/vfprintf.c?h=v1.1.6
Si elimina todo el soporte de flotador hexagonal, el soporte de infinito / nan, el soporte de variación %g
/ %f
/ %e
, el redondeo (que nunca será necesario si solo desea respuestas exactas) y otras cosas que podría no necesitar, el El código restante es bastante simple.
Sé que tal vez no sea necesario, pero hice una función que convierte float en cadena:
CÓDIGO:
#include <stdio.h>
/** Number on countu **/
int n_tu(int number, int count)
{
int result = 1;
while(count-- > 0)
result *= number;
return result;
}
/*** Convert float to string ***/
void float_to_string(float f, char r[])
{
long long int length, length2, i, number, position, sign;
float number2;
sign = -1; // -1 == positive number
if (f < 0)
{
sign = ''-'';
f *= -1;
}
number2 = f;
number = f;
length = 0; // Size of decimal part
length2 = 0; // Size of tenth
/* Calculate length2 tenth part */
while( (number2 - (float)number) != 0.0 && !((number2 - (float)number) < 0.0) )
{
number2 = f * (n_tu(10.0, length2 + 1));
number = number2;
length2++;
}
/* Calculate length decimal part */
for (length = (f > 1) ? 0 : 1; f > 1; length++)
f /= 10;
position = length;
length = length + 1 + length2;
number = number2;
if (sign == ''-'')
{
length++;
position++;
}
for (i = length; i >= 0 ; i--)
{
if (i == (length))
r[i] = ''/0'';
else if(i == (position))
r[i] = ''.'';
else if(sign == ''-'' && i == 0)
r[i] = ''-'';
else
{
r[i] = (number % 10) + ''0'';
number /=10;
}
}
}
Utilice snprintf()
de stdlib.h
. Trabajó para mi.
double num = 123412341234.123456789;
char output[50];
snprintf(output, 50, "%f", num);
printf("%s", output);
Utilizar esta:
void double_to_char(double f,char * buffer){
gcvt(f,10,buffer);
}
Vaya y observe la implementación de printf()
con "%f"
en alguna biblioteca de C.
Vea si la biblioteca estándar de BSD C tiene fcvt (). Podría comenzar con la fuente para eso, en lugar de escribir su código desde cero. El estándar fcvt () de UNIX 98 aparentemente no produce notación científica, por lo que tendría que implementarlo usted mismo, pero no creo que sea difícil.
sprintf puede hacer esto:
#include <stdio.h>
int main() {
float w = 234.567;
char x[__SIZEOF_FLOAT__];
sprintf(x, "%g", w);
puts(x);
}