float ejemplos and c++ c string floating-point floating-accuracy

c++ - ejemplos - Flotador de impresión, preservando la precisión.



float c++ ejemplos (8)

Estoy escribiendo un programa que imprime literales de punto flotante para usar dentro de otro programa.

¿Cuántos dígitos necesito imprimir para preservar la precisión del flotador original?

Como un flotador tiene 24 * (log(2) / log(10)) = 7.2247199 dígitos decimales de precisión, mi pensamiento inicial fue que la impresión de 8 dígitos debería ser suficiente. Pero si no tengo suerte, esos 0.2247199 se distribuyen a la izquierda ya la derecha de los 7 dígitos significativos, por lo que probablemente debería imprimir 9 dígitos decimales.

¿Mi análisis es correcto? ¿Son suficientes 9 dígitos decimales para todos los casos? Como printf("%.9g", x); ?

¿Existe una función estándar que convierte un flotante en una cadena con el número mínimo de dígitos decimales requerido para ese valor, en los casos donde 7 u 8 son suficientes, por lo que no imprimo dígitos innecesarios?

Nota: No puedo usar literales hexadecimales de punto flotante, porque C ++ estándar no los admite.


24 * (log (2) / log (10)) = 7.2247199

Eso es bastante representativo para el problema. No tiene ningún sentido expresar el número de dígitos significativos con una precisión de 0.0000001 dígitos. Usted está convirtiendo números a texto para el beneficio de un ser humano , no de una máquina. A un humano no le podría importar menos, y preferiría mucho, si escribieras

24 * (log (2) / log (10)) = 7

Intentar mostrar 8 dígitos significativos solo genera dígitos de ruido aleatorio. Con probabilidades distintas de cero, 7 ya es demasiado porque el error de punto flotante se acumula en los cálculos. Sobre todo, imprimir números usando una unidad de medida razonable. Las personas están interesadas en milímetros, gramos, libras, pulgadas, etcétera. Ningún arquitecto se preocupará por el tamaño de una ventana expresada con más precisión que 1 mm. Ninguna planta de fabricación de ventanas prometerá una ventana tan precisa como esa.

Por último, pero no menos importante, no puede ignorar la precisión de los números que ingresa a su programa. No es posible medir la velocidad de un trago europeo sin carga de hasta 7 dígitos. Tiene aproximadamente 11 metros por segundo, 2 dígitos como máximo. Por lo tanto, realizar cálculos en esa velocidad e imprimir un resultado que tenga dígitos más significativos produce resultados sin sentido que prometen una precisión que no existe.


Con algo como

def f(a): b=0 while a != int(a): a*=2; b+=1 return a, b

(que es Python) debería poder obtener la mantisa y el exponente sin pérdidas.

En C, esto probablemente sería

struct float_decomp { float mantissa; int exponent; } struct float_decomp decomp(float x) { struct float_decomp ret = { .mantissa = x, .exponent = 0}; while x != floor(x) { ret.mantissa *= 2; ret.exponent += 1; } return ret; }

Pero tenga en cuenta que todavía no todos los valores se pueden representar de esa manera, es solo un disparo rápido lo que debería dar una idea, pero probablemente necesita mejoras.


Para garantizar que un viaje binario-> decimal-> binario recupere el valor binario original, IEEE 754 requiere

The original binary value will be preserved by converting to decimal and back again using:[10] 5 decimal digits for binary16 9 decimal digits for binary32 17 decimal digits for binary64 36 decimal digits for binary128 For other binary formats the required number of decimal digits is 1 + ceiling(p*log10(2)) where p is the number of significant bits in the binary format, e.g. 24 bits for binary32.

En C, las funciones que puede usar para estas conversiones son snprintf () y strtof / strtod / strtold ().

Por supuesto, en algunos casos, incluso más dígitos pueden ser útiles (no, no siempre son "ruido", dependiendo de la implementación de las rutinas de conversión de decimales como snprintf ()). Considere, por ejemplo, imprimir fracciones diádicas .


Puedes usar sprintf . No estoy seguro de si esto responde a tu pregunta exactamente, pero de todos modos, aquí está el código de muestra

#include <stdio.h> int main( void ) { float d_n = 123.45; char s_cp[13] = { ''/0'' }; char s_cnp[4] = { ''/0'' }; /* * with sprintf you need to make sure there''s enough space * declared in the array */ sprintf( s_cp, "%.2f", d_n ); printf( "%s/n", s_cp ); /* * snprinft allows to control how much is read into array. * it might have portable issues if you are not using C99 */ snprintf( s_cnp, sizeof s_cnp - 1 , "%f", d_n ); printf( "%s/n", s_cnp ); getchar(); return 0; } /* output : * 123.45 * 123 */


Se garantiza que la conversión de punto flotante a decimal utilizada en Java producirá el menor número de dígitos decimales más allá del punto decimal necesario para distinguir el número de sus vecinos (más o menos).

Puede copiar el algoritmo desde aquí: http://www.docjar.com/html/api/sun/misc/FloatingDecimal.java.html Preste atención al constructor FloatingDecimal(float) y al método toJavaFormatString() .


Si el programa está destinado a ser leído por una computadora, yo haría el truco simple de usar el aliasing char* .

  • alias float* a char*
  • copiar en un aliasing unsigned (o cualquier tipo sin signo es lo suficientemente grande) a través de aliasing char*
  • imprimir el valor unsigned

La decodificación es simplemente revertir el proceso (y en la mayoría de las plataformas se puede usar un reinterpret_cast directo).


Si lees estos documentos (ver más abajo), encontrarás que hay algún algoritmo que imprime el número mínimo de dígitos decimales, de modo que el número puede ser reinterpretado sin cambios (es decir, con scanf).

Como puede haber varios números de este tipo, el algoritmo también elige la fracción decimal más cercana a la fracción binaria original (nombré valor flotante).

Una pena que no haya tal biblioteca estándar en C.


Si tiene una biblioteca de C que cumple con C99 (y si sus tipos de coma flotante tienen una base que es una potencia de 2 :), el carácter de formato de printf %a puede imprimir valores de punto flotante sin falta de precisión en forma hexadecimal, y las utilidades como strod y strod podrán leerlos.