Formato de punto flotante de doble precisión

Compartir Imprimir Citar
64-bit formato de número de computadora

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.

El punto flotante se usa para representar valores fraccionarios, o cuando se necesita un rango más amplio que el proporcionado por el punto fijo (del mismo ancho de bit), incluso a costa de la precisión. Se puede elegir la doble precisión cuando el rango o la precisión de la precisión simple sean insuficientes.

En el estándar IEEE 754-2008, el formato base-2 de 64 bits se denomina oficialmente binary64; fue llamado doble en IEEE 754-1985. IEEE 754 especifica formatos adicionales de coma flotante, incluidas las representaciones de precisión simple de base 2 de 32 bits y, más recientemente, representaciones de base 10.

Fortran fue uno de los primeros lenguajes de programación en proporcionar tipos de datos de punto flotante de precisión simple y doble. 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 el modelo de la computadora, y de las decisiones tomadas por los implementadores del lenguaje de programación. Por ejemplo, el tipo de datos de precisión doble de GW-BASIC era el formato de punto flotante MBF de 64 bits.

Formato binario de coma flotante de precisión doble IEEE 754: binary64

El punto flotante binario de doble precisión es un formato de uso común 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. Es comúnmente conocido simplemente como doble. El estándar IEEE 754 especifica que un binary64 tiene:

El bit de signo determina el signo del número (incluso cuando este número es cero, que tiene signo).

El campo de 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 de significado 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 un máximo de 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 la misma cantidad de dígitos, el resultado final debería 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.

El formato se escribe con la mantisa que tiene un bit entero implícito de valor 1 (excepto para datos especiales, consulte la codificación de exponente a continuación). Con los 52 bits de la fracción (F) apareciendo en el formato de memoria, la precisión total es por lo tanto de 53 bits (aproximadamente 16 dígitos decimales, 53 log10(2) ≈ 15,955). Los bits se distribuyen de la siguiente manera:

IEEE 754 Double Floating Point Format.svg

El valor real asumido por un dato de doble precisión de 64 bits con un exponente parcial dado e{displaystyle e} y una fracción de 52 bits

()− − 1)Signatura()1.b51b50...b0)2× × 2e− − 1023{displaystyle (-1)^{text{sign}}(1.b_{51}b_{50}...b_{0})_{2}times 2^{e-1023}

o

()− − 1)Signatura()1+.. i=152b52− − i2− − i)× × 2e− − 1023{displaystyle (-1)^{text{sign}left(1+sum ##{i=1} {52}b_{52-i}2^{-i}right]times 2^{e-1023}

Entre 252=4,503,599,627,370,496 y 253=9,007,199,254,740,992 los números representables son exactamente los enteros. Para el siguiente rango, de 253 a 254, todo se multiplica por 2, por lo que los números representables son los pares, etc. Por el contrario, para el rango anterior de 251 a 252, el espaciado es 0,5, etc.

El espaciado como fracción de los números en el rango de 2n a 2n+1 es 2n−52. El máximo error de redondeo relativo al redondear un número al representable más cercano (el épsilon de la máquina) es por lo tanto 2−53.

El ancho de 11 bits del exponente permite la representación de números entre 10−308 y 10308, con una precisión completa de 15 a 17 dígitos decimales. Al comprometer la precisión, la representación subnormal permite valores incluso más pequeños, hasta aproximadamente 5 × 10−324.

Codificación de exponentes

El exponente de punto flotante binario de precisión doble se codifica utilizando una representación binaria compensada, con el desplazamiento cero siendo 1023; también conocido como sesgo de exponente en el estándar IEEE 754. Ejemplos de tales representaciones serían:

e =000000000012=00116=1: 21− − 1023=2− − 1022{displaystyle 2^{1-1023}=2^{-1022}(smallest exponent for normal numbers)
e =011111111112=3ff16=1023: 21023− − 1023=20{displaystyle 2^{1023-1023}=2^{0}(cero compensado)
e =100000001012=40516=1029: 21029− − 1023=26{displaystyle 2^{1029-1023}=2^{6}
e =111111111102=7fe16=2046: 22046− − 1023=21023{displaystyle 2^{2046-1023}=2^{1023}(mayor exponente)

Los exponentes 00016 y 7ff16 tienen un significado especial:

donde F es la parte fraccionaria del significado. Todos los patrones de bits son codificación válida.

Excepto por las excepciones anteriores, el número completo de doble precisión se describe mediante:

()− − 1)Signatura× × 2e− − 1023× × 1.fracción{displaystyle (-1)^{text{sign}}times 2^{e-1023}times 1.{text{fraction}}}}

En el caso de números subnormales (e = 0), el número de doble precisión se describe mediante:

()− − 1)Signatura× × 21− − 1023× × 0.fracción=()− − 1)Signatura× × 2− − 1022× × 0.fracción{displaystyle (-1)^{text{sign}}times 2^{1-1023}times 0.{text{fraction}}=(-1)^{text{sign}}times 2^{-1022}times 0.{text{fraction}}}}}}}}}}}}}}}}}times 2^{-1022}times

Extremidad

Aunque muchos procesadores utilizan almacenamiento pequeño-endiano para todo tipo de datos (integer, punto flotante), hay una serie de arquitecturas de hardware donde los números de puntos flotantes están representados en forma de gran-endian mientras que los enteros están representados en forma poco-endiana. Hay procesadores de ARM que tienen una representación de punta flotante mixta para números de doble precisión: cada una de las dos palabras de 32 bits se almacena como pequeño-endiano, pero la palabra más significativa se almacena primero. El punto flotante VAX almacena palabras de 16 bits poco finas en orden grande. Debido a que ha habido muchos formatos de punto flotante sin representación estándar de red para ellos, el estándar XDR utiliza IEEE 754 como su representación. Por lo tanto, puede parecer extraño que el estándar generalizado IEEE 754 no especifica el endianness. Teóricamente, esto significa que incluso los datos estándar de punta flotante de IEEE escritos por una máquina podrían no ser legibles por otra. Sin embargo, en las computadoras estándar modernas (es decir, la implementación de IEEE 754), se puede suponer con seguridad que el endianness es el mismo para los números de puntos flotantes que para los enteros, haciendo la conversión directamente independientemente del tipo de datos. Los pequeños sistemas incrustados usando formatos especiales de punto flotante pueden ser otra materia, sin embargo.

Ejemplos de doble precisión

0 0111111111110 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 ≙ 3FF0 0000 0000 000016 ≙ +20 × 1 = 1
0111111111111 00000000000000000000000000000000000000000000000000012 ≙ 3FF0 0000 0000 000 000116 ≙ +20 × 1 + 2−52) ♥ 1.0000000000000002, el número más pequeño 1
0 01111111111 00000000000000000000000000000000000000000000000000000000000102 ≙ 3FF0 0000 0000 000 000216 ≙ +20 × 1 + 2.51 -♥ 1.0000000000004
0 10.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 ≙ 4000 0000 0000 000016 ≙ +21 × 1 = 2
1 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 ≙ C000 0000 0000 000016 ≙ −21 × 1 = 2
0 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 ≙ 4008 0000 0000 000016 ≙ +21 × 1.12 = 112 = 3
0 10000000001 00000000000000000000000000000000000000000000000000000000000000000000000000002 ≙ 4010 0000 0000 000016 ≙ +22 × 1 = 1002 = 4
0 10000000001 01000000000000000000000000000000000000000000000000000000000000002 ≙ 4014 0000 0000 000016 ≙ +22 × 1.012 = 1012 = 5
0 10000000001 10000000000000000000000000000000000000000000000000000000000000000000002 ≙ 4018 0000 0000 000016 ≙ +22 × 1.12 = 1102 = 6
0 10000000011 01110000000000000000000000000000000000000000000000000000000000000000000000000002 ≙ 4037 0000 0000 000016 ≙ +24 × 1.01112 = 101112 = 23
0 01111111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 ≙ 3F88 0000 0000 000016 ≙ +2−7 × 1.12 = 0,000000112 = 0,01171875 (3/256)
0 0000000000000000000000000000000000000000000000000000000000000000000000012 ≙ 0000 0000 0000 000 000116 ≙ +2−10-22 × 2−52 = 2−1074 ■ 4.9406564584124654 × 10−324 (Min. subnormal positivo doble)
0 00000000000 11111111111111111111111111111111111111111111111111111111111111111111111111112 000 000F FFFF FFFF FFFF16 ≙ +2−10-22 × (1 − 2−52) ♥ 2.2250738585072009 × 10−308 (Max. doble subnormal)
0 00000000001 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 ≙ 0010 0000 0000 000016 ≙ +2−10-22 × 1 Ω 2.2250738585072014 × 10−308 (Min. normal positivo doble)
0 1111111111110 11111111111111111111111111111111111111111111111111111111111111111111111111111111112 FE 7FEF FFFF FFFF16 ≙ +21023 × 1 + (1 − 2−52) ♥ 1.7976931348623157 × 10308 (Max. Double)
0 00000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 ≙ 0000 0000 0000 000016 ≙ +0
1 00000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 ≙ 8000 0000 0000 000016 ≙ −0
0 1111111111110 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 ≙ 7FF0 0000 0000 000016 (infinito positivo)
1 1111111111110 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 ≙ FFF0 0000 000016 (infinito negativo)
0 1111111111111 00000000000000000000000000000000000000000000000000012 ≙ 7FF0 0000 0000 000 000116 ≙ NaN (sNaN en la mayoría de los procesadores, como x86 y ARM)
0 1111111111111 10000000000000000000000000000000000000000000000012 ≙ 7FF8 0000 0000 000 000116 ≙ NaN (qNan en la mayoría de los procesadores, como x86 y ARM)
0 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111112 ≙ 7FFF FFFF FFFF FFFF16 ≙ NaN (una codificación alternativa de NaN)
0 01111111101 010101010101010101010101010101010101010101010101010101012 = 3FD5 5555 5555 555516 ≙ +2−2 × 1 + 2−2 + 2−4 +... + 2−52) 1/3
0 10000000000 10010010000111111010101000100010000101101000110002 4009 21FB 5444 2D1816 Entendido.

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 la familia x86 y los procesadores de la familia ARM, usan el bit más significativo del campo significativo para indicar un NaN tranquilo; esto es lo que recomienda IEEE 754. Los procesadores PA-RISC usan el bit para indicar una señalización NaN.

De forma predeterminada, 1/3 redondea hacia abajo, en lugar de hacia arriba como precisión simple, debido al número impar de bits en la mantisa.

Con más detalle:

Dada la representación hexadecimal 3FD5 5555 5555 555516,
Signatura = 0
Exponent = 3FD16 = 1021
Bias exponentes = 1023 (valor constante; véase más arriba)
Fracción = 5 5555 5555 555516Valor = 2(Exponent − Exponent Bias) × 1.Fraction – Tenga en cuenta que la Fracción no debe convertirse en decimal aquí
= 2−2 × (15 5555 5555 555516 × 2−52)
= 2−54 × 15 5555 5555 555516= 0,3333333333333333314829616256247390992939472198486328125
Entendido 1/3

Velocidad de ejecución con aritmética de doble precisión

Usar variables de punto flotante de precisión doble suele ser más lento que trabajar con sus equivalentes de precisión simple. Un área de la informática en la que este es 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 tardan, dependiendo del hardware, aproximadamente de 2 a 32 veces más en completarse en comparación con los que se realizan con precisión simple.

Además, muchas funciones matemáticas (p. ej., 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.

Limitaciones de precisión en valores enteros

Implementaciones

Los dobles se implementan en muchos lenguajes de programación de diferentes maneras, como las siguientes. En procesadores con solo 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++

C y C++ ofrecen una amplia variedad de tipos aritméticos. Los estándares no exigen la 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 tipo double corresponde a la doble precisión. Sin embargo, en x86 de 32 bits con precisión ampliada de forma predeterminada, es posible que algunos compiladores no se ajusten al estándar C o que la aritmética sufra un doble redondeo.

Fortran

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.

Ceceo común

Common Lisp proporciona los tipos SHORT-FLOAT, SINGLE-FLOAT, DOUBLE-FLOAT y LONG-FLOAT. 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 capturar subdesbordamientos y desbordamientos de coma flotante, y la excepción de coma flotante inexacta, según IEEE 754. No se describen infinitos ni NaN en el estándar ANSI, sin embargo, varias implementaciones los proporcionan como extensiones.

Java

En Java antes de la versión 1.2, cada implementación tenía que ser compatible con IEEE 754. La versión 1.2 permitió implementaciones para brindar precisión adicional en cálculos intermedios para plataformas como x87. Por lo tanto, se introdujo un modificador strictfp para hacer cumplir los cálculos estrictos de IEEE 754. El punto flotante estricto se ha restaurado en Java 17.

Javascript

Según lo especificado por el estándar ECMAScript, toda la aritmética en JavaScript se realizará utilizando aritmética de coma flotante de doble precisión.

JSON

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 cuanto a la precisión o el rango de los números así codificados. Sin embargo, RFC 8259 advierte que, dado que los números binary64 de IEEE 754 están ampliamente implementados, se puede lograr una buena interoperabilidad mediante implementaciones que procesan JSON si no esperan más precisión o rango que las ofertas de binary64.

Notas y referencias

  1. ^ William Kahan (1o de octubre de 1997). "Lecturas Notas sobre el estado de IEEE Estándar 754 para la Aritmética del Punto de Flotación binaria" (PDF). Archivado (PDF) original el 8 de febrero de 2012.
  2. ^ Savard, John J. G. (2018) [2005], "Floating-Point Formats", quadibloc, archivado desde el original en 2018-07-03, recuperado 2018-07-16
  3. ^ "paquete – convertir una lista en una representación binaria".
  4. ^ "Nvidia's New Titan V empuja 110 Teraflops de un solo chip". El Hardware de Tom. 2017-12-08. Retrieved 2018-11-05.
  5. ^ "Bug 323 – código optimizado da resultados de puntos flotantes extraños". gcc.gnu.org. Archivado desde el original el 30 de abril de 2018. Retrieved 30 de abril 2018.
  6. ^ Darcy, Joseph D. "JEP 306: Restore Always-Strict Floating-Point Semantics". Retrieved 2021-09-12.
  7. ^ ECMA-262 ECMAScript Especificación del idioma (PDF) (5th ed.). Ecma International. p. 29, §8.5 Tipo de número. Archivado (PDF) del original en 2012-03-13.
  8. ^ "The JavaScript Object Notation (JSON) Data Interchange Format". Equipo de Tareas de Ingeniería de Internet. Diciembre de 2017. Retrieved 2022-02-01.