precisión 'flotante' versus 'doble'

155

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);

te dará la salida

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

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

foo
fuente

Respuestas:

146

Los números de coma flotante en C usan la codificación IEEE 754 .

Este tipo de codificación utiliza un signo, un significado y un exponente.

Debido a esta codificación, muchos números tendrán pequeños cambios para permitir que se almacenen.

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 (flotante) 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.

Alan Geleynse
fuente
44
C99 sí, anteriormente dependía del compilador.
Alan Geleynse
21
-1 Esta afirmación es descaradamente falsa: "Debido a esta codificación, nunca puede garantizar que no tendrá un cambio en su valor".
R .. GitHub DEJA DE AYUDAR A ICE
16
@Alan: C99 no requiere punto flotante IEEE; solo lo recomienda.
R .. GitHub DEJA DE AYUDAR AL HIELO
44
@Alan: R .. es correcto; El Anexo F (que especifica los enlaces IEEE-754) es normativo, pero solo en efecto si se define una implementación __STDC_IEC_559__. Una implementación que no define esa macro es libre de no cumplir con IEEE-754.
Stephen Canon
12
@Alan: Bajo IEEE 754, es fácil garantizar que no hay ningún cambio en los valores 0.5, 0.046875o 0.376739501953125frente a sus representaciones decimales. (Estos son todos los números racionales diádicas con accesorio numerador en la mantisa y logaritmo en base 2 del accesorio en el exponente denominador.)
R .. GitHub dejar de ayudar a ICE
42

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

No. Los dobles siempre tienen 53 bits significativos y los flotantes siempre tienen 24 bits significativos (excepto los valores denormales, infinitos y NaN, pero esos son temas para una pregunta diferente). Estos son formatos binarios, y solo 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 de 32 bits sin signo puede almacenar enteros de hasta 32 bits, lo que no se asigna con precisión a 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 cifras significativas?

La codificación de un doble utiliza 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).

Stephen Canon
fuente
15

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.

abe312
fuente
11

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 una precisión específica para flotantes y dobles (aparte del hecho de que 1 y 1 + 1E-5/ 1 + 1E-7son distinguibles [ floaty doublerespectivamente]). Sin embargo, el número de cifras significativas se deja al implementador (así como a la base que utilizan 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_RADIXy FLT_MANT_DIG(y DBL_MANT_DIG/ LDBL_MANT_DIG) se definen en float.h.

La razón por la que se llama a doublees 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 compiladores) asigna relativamente más bits para el significado que el exponente (23 a 9 para floatvs. 52 a 12 para double), por lo que 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 )

usuario470379
fuente
¿Error de tipografía? C89 requiere un épsilon de como máximo 1E-9para double, no 1E-7.
Rufflewind
10

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

Chris Nash
fuente
Detalle: binary64 tiene 53 bits significativos (52 almacenados explícitamente) binary32 tiene 24 bits (23 almacenados explícitamente).
chux - Restablece a Monica
4

No es exactamente doble precisión debido a cómo funciona IEEE 754 , y porque el binario realmente no se traduce bien a decimal. Echa un vistazo a la norma si estás interesado.

usuario541686
fuente
4

flotante significa número de coma flotante. En C, el tipo de datos flotante se utiliza en aquellos casos en que la precisión del número total de dígitos es 7.Por ejemplo: - el número decimal. 12.3546987 no se puede almacenar en flotante porque tiene un total de 9 dígitos. La salida se mostrará como 12.354699, es decir, los primeros 7 dígitos se mostrarán como ingresados ​​en la entrada y el octavo dígito se redondeará. El tipo flotante puede representar valores que varía de aproximadamente 1.5 x 10 ^ (- 45) a 3.4 x 10 ^ (38). En términos de asignación de memoria, flotante es un tipo de datos de coma flotante de 32 bits de precisión simple.

A diferencia del flotante, el doble tiene una precisión de 15 a 16 dígitos. El rango del doble es de 5.0 × 10 ^ (- 345) a 1.7 × 10 ^ (308). En términos de asignación de bytes, el doble es un dato de coma flotante de 64 bits tipo.

El problema surge en su uso. Flotante o doble no afecta a printf pero en caso de scanf se debe utilizar el tipo de datos apropiado dependiendo del número total. de dígitos en flotante no. eso debe ser leído desde la entrada.

Por lo tanto, se prefiere el doble sobre el flotante para una mayor precisión de los datos.

Espero que esto ayude.

Vineeth Krishna K
fuente