El formato de punto flotante de doble precisión (a veces llamado FP64 o float64 ) es un formato de número de punto flotante , que normalmente ocupa 64 bits en la memoria de la computadora; representa un amplio rango dinámico de valores numéricos mediante el uso de un punto de base flotante .
Se podrá elegir la doble precisión cuando el alcance o la precisión de la precisión simple sean insuficientes.
En el estándar IEEE 754 , el formato base-2 de 64 bits se denomina oficialmente binario64 ; se llamó doble en IEEE 754-1985 . IEEE 754 especifica formatos de punto flotante adicionales, incluidas representaciones de precisión simple de base 2 de 32 bits y, más recientemente, representaciones de base 10 ( punto flotante decimal ).
Uno de los primeros lenguajes de programación que proporcionó tipos de datos de punto flotante fue Fortran . [ cita necesaria ] Antes de la adopción generalizada de IEEE 754-1985, la representación y las propiedades de los tipos de datos de punto flotante dependían del fabricante y del modelo de la computadora, y de las decisiones tomadas por los implementadores del lenguaje de programación. Por ejemplo, el tipo de datos de doble precisión de GW-BASIC era el formato de punto flotante MBF de 64 bits .
El punto flotante binario de doble precisión es un formato comúnmente utilizado en las PC, debido a su rango más amplio que el punto flotante de precisión simple, a pesar de su rendimiento y costo de ancho de banda. Se le conoce comúnmente simplemente como doble . El estándar IEEE 754 especifica que un binario64 tiene:
El bit de signo determina el signo del número (incluso cuando este número es cero, que tiene signo ).
El campo exponente es un entero sin signo de 11 bits de 0 a 2047, en forma sesgada : un valor de exponente de 1023 representa el cero real. Los exponentes varían de −1022 a +1023 porque los exponentes de −1023 (todos 0) y +1024 (todos 1) están reservados para números especiales.
La precisión significativa de 53 bits proporciona una precisión de 15 a 17 dígitos decimales significativos (2 −53 ≈ 1,11 × 10 −16 ). Si una cadena decimal con como máximo 15 dígitos significativos se convierte al formato de doble precisión IEEE 754, dando un número normal, y luego se vuelve a convertir a una cadena decimal con el mismo número de dígitos, el resultado final debe coincidir con la cadena original. Si un número de doble precisión IEEE 754 se convierte en una cadena decimal con al menos 17 dígitos significativos y luego se vuelve a convertir a una representación de doble precisión, el resultado final debe coincidir con el número original. [1]
El formato se escribe con el significado teniendo un bit entero implícito de valor 1 (excepto para datos especiales, consulte la codificación del exponente a continuación). Con los 52 bits del significado de la fracción (F) que aparecen en el formato de memoria, la precisión total es, por tanto, de 53 bits (aproximadamente 16 dígitos decimales, 53 log 10 (2) ≈ 15,955). Los bits se distribuyen de la siguiente manera:
El valor real asumido por un dato de doble precisión dado de 64 bits con un exponente sesgado dado y una fracción de 52 bits es
o
Entre 2 52 = 4.503.599.627.370.496 y 2 53 = 9.007.199.254.740.992 los números representables son exactamente los números enteros. Para el siguiente rango, de 2 53 a 2 54 , todo se multiplica por 2, por lo que los números representables son los pares, etc. Por el contrario, para el rango anterior de 2 51 a 2 52 , el espaciado es 0,5, etc.
El espaciado como fracción de los números en el rango de 2 n a 2 n +1 es 2 n −52 . El error de redondeo relativo máximo al redondear un número al representable más cercano (la máquina épsilon ) es, por tanto, 2 −53 .
El ancho de 11 bits del exponente permite la representación de números entre 10 −308 y 10 308 , con una precisión completa de 15 a 17 dígitos decimales. Al comprometer la precisión, la representación subnormal permite valores aún más pequeños de hasta aproximadamente 5 × 10 −324 .
El exponente binario de coma flotante de doble precisión se codifica utilizando una representación binaria con desplazamiento , siendo el desplazamiento cero 1023; También conocido como sesgo de exponente en el estándar IEEE 754. Ejemplos de tales representaciones serían:
Los exponentes y tienen un significado especial:00016
7ff16
000000000002
= se utiliza para representar un cero con signo (si F = 0) y números subnormales (si F ≠ 0); y00016
111111111112
= se usa para representar ∞ (si F = 0) y NaN (si F ≠ 0),7ff16
donde F es la parte fraccionaria del significado . Todos los patrones de bits son codificación válida.
Salvo las excepciones anteriores, el número completo de doble precisión se describe mediante:
En el caso de números subnormales ( e = 0), el número de doble precisión se describe mediante:
Las codificaciones de qNaN y sNaN no están completamente especificadas en IEEE 754 y dependen del procesador. La mayoría de los procesadores, como los procesadores de la familia x86 y la familia ARM , utilizan el bit más significativo del campo significativo para indicar un NaN silencioso; esto es lo que recomienda IEEE 754. Los procesadores PA-RISC utilizan el bit para indicar una señalización NaN.
De forma predeterminada, 1/3 se redondea hacia abajo, en lugar de hacia arriba como la precisión simple , debido al número impar de bits en el significado.
Con más detalle:
Dada la representación hexadecimal 3FD5 5555 5555 5555 16 , Signo = 0 Exponente = 3FD 16 = 1021 Sesgo del exponente = 1023 (valor constante; ver arriba) Fracción = 5 5555 5555 5555 16 Valor = 2 (Exponente − Sesgo del exponente) × 1.Fracción: tenga en cuenta que la fracción no se debe convertir a decimal aquí = 2 −2 × (15 5555 5555 5555 16 × 2 −52 ) = 2 −54 × 15 5555 5555 5555 16 = 0,333333333333333314829616256247390992939472198486328125 ≈ 1/3
El uso de variables de punto flotante de doble precisión suele ser más lento que trabajar con sus contrapartes de precisión simple. Un área de la informática donde esto representa un problema particular es el código paralelo que se ejecuta en GPU. Por ejemplo, cuando se utiliza la plataforma CUDA de NVIDIA , los cálculos con doble precisión pueden tardar, según el hardware, de 2 a 32 veces más en completarse en comparación con los realizados con precisión simple . [4]
Además, muchas funciones matemáticas (por ejemplo, sin, cos, atan2, log, exp y sqrt) necesitan más cálculos para dar resultados precisos de doble precisión y, por lo tanto, son más lentas.
Los dobles se implementan en muchos lenguajes de programación de diferentes maneras, como las siguientes. En procesadores que solo tienen precisión dinámica, como x86 sin SSE2 (o cuando no se usa SSE2, por motivos de compatibilidad) y con precisión extendida utilizada de forma predeterminada, el software puede tener dificultades para cumplir con algunos requisitos.
C y C++ ofrecen una amplia variedad de tipos aritméticos . Los estándares no exigen doble precisión (excepto el anexo F opcional de C99 , que cubre la aritmética IEEE 754), pero en la mayoría de los sistemas, el double
tipo corresponde a doble precisión. Sin embargo, en x86 de 32 bits con precisión extendida de forma predeterminada, es posible que algunos compiladores no se ajusten al estándar C o que la aritmética pueda sufrir un doble redondeo . [5]
Fortran proporciona varios tipos enteros y reales, y el tipo de 64 bits real64
, accesible a través del módulo intrínseco de Fortran iso_fortran_env
, corresponde a la doble precisión.
Common Lisp proporciona los tipos FLOAT CORTO, FLOTADOR ÚNICO, FLOTADOR DOBLE y FLOTADOR LARGO. La mayoría de las implementaciones proporcionan SINGLE-FLOAT y DOUBLE-FLOAT con los otros tipos de sinónimos apropiados. Common Lisp proporciona excepciones para detectar desbordamientos y subdesbordamientos de punto flotante, y la excepción de punto flotante inexacto, según IEEE 754. No se describen infinitos ni NaN en el estándar ANSI; sin embargo, varias implementaciones los proporcionan como extensiones.
En Java anterior a la versión 1.2, cada implementación tenía que ser compatible con IEEE 754. La versión 1.2 permitió que las implementaciones aportaran precisión adicional en los cálculos intermedios para plataformas como x87 . Por lo tanto , se introdujo un modificador estrictofp para imponer cálculos estrictos de IEEE 754. El punto flotante estricto se ha restaurado en Java 17. [6]
Según lo especificado por el estándar ECMAScript , toda la aritmética en JavaScript se realizará utilizando aritmética de punto flotante de doble precisión. [7]
El formato de codificación de datos JSON admite valores numéricos y la gramática a la que deben ajustarse las expresiones numéricas no tiene límites en la precisión o el rango de los números así codificados. Sin embargo, RFC 8259 advierte que, dado que los números binarios64 IEEE 754 están ampliamente implementados, se puede lograr una buena interoperabilidad mediante implementaciones que procesen JSON si no esperan más precisión o rango que el que ofrece binario64. [8]