‘float’ contra ‘doble’ precisión

El código

float x = 3.141592653589793238; double z = 3.141592653589793238; printf("x=%f\n", x); printf("z=%f\n", z); printf("x=%20.18f\n", x); printf("z=%20.18f\n", z); 

le dará la salida

 x=3.141593 z=3.141593 x=3.141592741012573242 z=3.141592653589793116 

donde en la tercera línea de salida 741012573242 es basura y en la cuarta línea 116 es basura. ¿Los dobles siempre tienen 16 cifras significativas, mientras que las carrozas siempre tienen 7 cifras significativas? ¿Por qué los dobles no tienen 14 figuras significativas?

Los números de coma flotantes en C usan la encoding IEEE 754 .

Este tipo de encoding utiliza un signo, un significado y un exponente.

Debido a esta encoding, muchos números tendrán pequeños cambios para permitir su almacenamiento.

Además, el número de dígitos significativos puede cambiar ligeramente ya que es una representación binaria, no decimal.

La precisión simple (float) le proporciona 23 bits de significado, 8 bits de exponente y 1 bit de signo.

La precisión doble (doble) le proporciona 52 bits de significado, 11 bits de exponente y 1 bit de signo.

¿Los dobles siempre tienen 16 cifras significativas, mientras que las carrozas siempre tienen 7 cifras significativas?

No. Los dobles siempre tienen 53 bits significativos y los flotantes siempre tienen 24 bits significativos (a excepción de los valores denoriales, infinitos y NaN, pero esos son sujetos para una pregunta diferente). Estos son formatos binarios, y solo se puede hablar claramente sobre la precisión de sus representaciones en términos de dígitos binarios (bits).

Esto es análogo a la pregunta de cuántos dígitos se pueden almacenar en un entero binario: un entero sin signo de 32 bits puede almacenar enteros de hasta 32 bits, lo que no se correlaciona con precisión con ningún número de dígitos decimales: todos los enteros de hasta Se pueden almacenar 9 dígitos decimales, pero también se pueden almacenar muchos números de 10 dígitos.

¿Por qué los dobles no tienen 14 figuras significativas?

La encoding de un doble usa 64 bits (1 bit para el signo, 11 bits para el exponente, 52 bits significativos explícitos y un bit implícito), que es el doble del número de bits utilizados para representar un flotante (32 bits).

Un flotador tiene 23 bits de precisión, y un doble tiene 52.

Por lo general, se basa en cifras significativas tanto del exponente como del significado en la base 2, no en la base 10. De lo que puedo decir en el estándar C99, sin embargo, no hay precisión especificada para flotantes y dobles (aparte del hecho de que 1 y 1 + 1E-5 / 1 + 1E-7 son distinguibles [ float y double repsectivamente]). Sin embargo, la cantidad de cifras significativas se deja al implementador (así como también la base que usa internamente, por lo que, en otras palabras, una implementación podría decidir hacerlo en base a 18 dígitos de precisión en la base 3). [1]

Si necesita conocer estos valores, las constantes FLT_RADIX y FLT_MANT_DIG (y DBL_MANT_DIG / LDBL_MANT_DIG ) se definen en float.h.

La razón por la que se llama double es porque el número de bytes utilizados para almacenarlo es el doble del número de un flotante (pero esto incluye tanto el exponente como el significado). El estándar IEEE 754 (utilizado por la mayoría de los comstackdores) asigna relativamente más bits para el significado que el exponente (23 a 9 para float contra 52 a 12 para double ), razón por la cual la precisión es más del doble.

1: Sección 5.2.4.2.2 ( http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf )

flotante: 23 bits de significado, 8 bits de exponente y 1 bit de signo.

doble: 52 bits de significado, 11 bits de exponente y 1 bit de signo.

No es exactamente una precisión doble debido a la forma en que funciona el IEEE 754 , y porque el binario en realidad no se puede traducir bien a decimal. Eche un vistazo a la norma si está interesado.