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 una amplia gama de valores numéricos mediante el uso de un punto de base flotante .
Se puede optar por la doble precisión cuando el rango o la precisión de la precisión simple resulten insuficientes.
En el estándar IEEE 754 , el formato de base 2 de 64 bits se denomina oficialmente binary64 ; en IEEE 754-1985 se llamaba double . IEEE 754 especifica formatos de punto flotante adicionales, incluyendo precisión simple de base 2 de 32 bits y, más recientemente, representaciones en base 10 ( punto flotante decimal ).
Uno de los primeros lenguajes de programación en ofrecer tipos de datos de punto flotante fue Fortran . Antes de la adopción generalizada de la norma IEEE 754-1985, la representación y las propiedades de los tipos de datos de punto flotante dependían del fabricante y el modelo del ordenador, así como de las decisiones tomadas por los desarrolladores 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 .
Formato binario de punto flotante de doble precisión IEEE 754: binary64
El formato binario de punto flotante de doble precisión es un formato comúnmente utilizado en PC, debido a su mayor rango en comparación con el punto flotante de precisión simple, a pesar de su menor rendimiento y consumo de ancho de banda. Se le conoce comúnmente como double . El estándar IEEE 754 especifica que un binary64 tiene:
- Bit de signo : 1 bit
- Exponente : 11 bits
- Precisión significativa : 53 bits (52 almacenados explícitamente)
El bit de signo determina el signo del número (incluso cuando este número es cero, que es signo ).
El campo del exponente es un entero sin signo de 11 bits, de 0 a 2047, en formato sesgado : un valor de exponente de 1023 representa el cero real. Los exponentes van de −1022 a +1023 porque los exponentes de −1023 (todos ceros) y +1024 (todos unos) están reservados para números especiales.
La precisión de mantisa de 53 bits proporciona una precisión de entre 15 y 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 como resultado 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 debería coincidir con la cadena original. Si un número de doble precisión IEEE 754 se convierte a una cadena decimal con al menos 17 dígitos significativos, y luego se vuelve a convertir a la representación de doble precisión, el resultado final debe coincidir con el número original. [ 1 ]
El formato se escribe con la mantisa teniendo un bit entero implícito de valor 1 (excepto para datos especiales, véase la codificación del exponente más abajo). Con los 52 bits de la mantisa de 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 log 10 (2) ≈ 15,955). Los bits se disponen de la siguiente manera:
![]()
El valor real asumido por un dato de doble precisión de 64 bits dado con un exponente sesgado dado y una fracción de 52 bits es
o
Entre 2⁵² = 4.503.599.627.370.496 y 2⁵³ = 9.007.199.254.740.992, los números representables son exactamente los enteros. Para el siguiente rango, de 2⁵³ a 2⁵⁴ , 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⁵¹ a 2⁵² , 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 . Por lo tanto, el error de redondeo relativo máximo al redondear un número al más cercano representable (el épsilon de la máquina ) es 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, hasta aproximadamente 5 × 10 −324 .
Codificación exponencial
El exponente binario de punto flotante de doble precisión se codifica utilizando una representación binaria con desplazamiento , donde el desplazamiento cero es 1023; también conocido como sesgo del exponente en el estándar IEEE 754. Ejemplos de dichas representaciones serían:
Los exponentes y tienen un significado especial:000167ff16
000000000002= se utiliza para representar un cero con signo (si F = 0) y números subnormales (si F ≠ 0); y00016111111111112= se utiliza para representar ∞ (si F = 0) y NaNs (si F ≠ 0),7ff16
donde F es la parte fraccionaria de la mantisa . Todos los patrones de bits son una codificación válida.
Salvo las excepciones mencionadas anteriormente, el número de doble precisión completo se describe mediante:
En el caso de números subnormales ( e = 0), el número de doble precisión se describe mediante:
Endianidad
Aunque muchos procesadores usan almacenamiento little-endian para todos los tipos de datos (entero, punto flotante), hay varias arquitecturas de hardware donde los números de punto flotante se representan en formato big-endian mientras que los enteros se representan en formato little-endian. [ 2 ] Hay procesadores ARM que tienen representación de punto flotante mixed-endian para números de doble precisión: cada una de las dos palabras de 32 bits se almacena como little-endian, pero la palabra más significativa se almacena primero. El punto flotante VAX almacena palabras little-endian de 16 bits en orden big-endian. Debido a que ha habido muchos formatos de punto flotante sin una representación estándar de red para ellos, el estándar XDR usa big-endian IEEE 754 como su representación. Por lo tanto, puede parecer extraño que el estándar de punto flotante IEEE 754, ampliamente extendido , no especifique el endianness. [ 3 ] Teóricamente, esto significa que incluso los datos de punto flotante IEEE estándar escritos por una máquina podrían no ser legibles por otra. Sin embargo, en los ordenadores modernos estándar (es decir, que implementan IEEE 754), se puede asumir con seguridad que el orden de bytes es el mismo para los números de coma flotante que para los enteros, lo que simplifica la conversión independientemente del tipo de dato. No obstante, los sistemas embebidos pequeños que utilizan formatos especiales de coma flotante pueden presentar un problema diferente.
Ejemplos de doble precisión
0 01111111111 0000000000000000000000000000000000000000000000000000 2 ≙ 3FF0 0000 0000 0000 16 ≙ +2 0 × 1 = 1
0 01111111111 000000000000000000000000000000000000000000000000001 2 ≙ 3FF0 0000 0000 0001 16 ≙ +2 0 × (1 + 2 −52 ) ≈ 1,0000000000000002220 (el número más pequeño mayor que 1)
0 01111111111 000000000000000000000000000000000000000000000000010 2 ≙ 3FF0 0000 0000 0002 16 ≙ +2 0 × (1 + 2 −51 ) ≈ 1,0000000000000004441 (el segundo número más pequeño mayor que 1)
0 10000000000 000000000000000000000000000000000000000000000000000 2 ≙ 4000 0000 0000 0000 16 ≙ +2 1 × 1 = 2
1 10000000000 000000000000000000000000000000000000000000000000000 2 ≙ C000 0000 0000 0000 16 ≙ −2 1 × 1 = −2
0 10000000000 1000000000000000000000000000000000000000000000000000 2 ≙ 4008 0000 0000 0000 16 ≙ +2 1 × 1.1 2 = 11 2 = 3
0 10000000001 0000000000000000000000000000000000000000000000000000 2 ≙ 4010 0000 0000 0000 16 ≙ +2 2 × 1 = 100 2 = 4
0 10000000001 0100000000000000000000000000000000000000000000000000 2 ≙ 4014 0000 0000 0000 16 ≙ +2 2 × 1.01 2 = 101 2 = 5
0 10000000001 1000000000000000000000000000000000000000000000000000 2 ≙ 4018 0000 0000 0000 16 ≙ +2 2 × 1.1 2 = 110 2 = 6
0 10000000011 0111000000000000000000000000000000000000000000000000 2 ≙ 4037 0000 0000 0000 16 ≙ +2 4 × 1.0111 2 = 10111 2 = 23
0 01111111000 10000000000000000000000000000000000000000000000000000 2 ≙ 3F88 0000 0000 0000 16 ≙ +2 −7 × 1,1 2 = 0,00000011 2 = 0,01171875 (3/256)
0 00000000000 00000000000000000000000000000000000000000000000001 2 ≙ 0000 0000 0000 0001 16 ≙ +2 −1022 × 2 −52 = 2 −1074 ≈ 4.9406564584124654 × 10 −324 (número subnormal positivo más pequeño)
0 00000000000 11111111111111111111111111111111111111111111111111111 2 ≙ 000F FFFF FFFF FFFF 16 ≙ +2 −1022 × (1 − 2 −52 ) ≈ 2,2250738585072009 × 10 −308 (número subnormal más grande)
0 00000000001 0000000000000000000000000000000000000000000000000000 2 ≙ 0010 0000 0000 0000 16 ≙ +2 −1022 × 1 ≈ 2,2250738585072014 × 10 −308 (número normal positivo más pequeño)
0 111111111110 11111111111111111111111111111111111111111111111111111 2 ≙ 7FEF FFFF FFFF FFFF 16 ≙ +2 1023 × (2 − 2 −52 ) ≈ 1,7976931348623157 × 10³⁰⁸ (número normal más grande)
0 00000000000 0000000000000000000000000000000000000000000000000000 2 ≙ 0000 0000 0000 0000 16 ≙ +0 (cero positivo)
1 00000000000 000000000000000000000000000000000000000000000000000 2 ≙ 8000 0000 0000 0000 16 ≙ −0 (cero negativo)
0 11111111111 0000000000000000000000000000000000000000000000000000 2 ≙ 7FF0 0000 0000 0000 16 ≙ +∞ (infinito positivo)
1 11111111111 0000000000000000000000000000000000000000000000000000 2 ≙ FFF0 0000 0000 0000 16 ≙ −∞ (infinito negativo)
0 11111111111 000000000000000000000000000000000000000000000000001 2 ≙ 7FF0 0000 0000 0001 16 ≙ NaN (sNaN en la mayoría de los procesadores, como x86 y ARM)
0 11111111111 100000000000000000000000000000000000000000000000001 2 ≙ 7FF8 0000 0000 0001 16 ≙ NaN (qNaN en la mayoría de los procesadores, como x86 y ARM)
0 11111111111 111111111111111111111111111111111111111111111111111111 2 ≙ 7FFF FFFF FFFF FFFF 16 ≙ NaN (una codificación alternativa de NaN)
0 01111111101 0101010101010101010101010101010101010101010101010101 2 ≙ 3FD5 5555 5555 5555 16 ≙ +2 −2 × (1 + 2 −2 + 2 −4 + ... + 2 −52 ) ≈ 0,33333333333333331483 (aproximación más cercana a 1/3 )
0 10000000000 1001001000011111101101010100010001000010110100011000 2 ≙ 4009 21FB 5444 2D18 16 ≈ 3.141592653589793116 (aproximación más cercana a π)
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 de la familia x86 y ARM , utilizan el bit más significativo del campo mantisa para indicar un NaN silencioso; esto es lo que recomienda IEEE 754. Los procesadores PA-RISC utilizan el bit para indicar un NaN de señalización.
Por defecto, 1/3 redondea hacia abajo, en lugar de hacia arriba como en precisión simple , debido a la cantidad impar de bits en la mantisa.
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; véase más 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 debe convertirse a decimal aquí = 2 −2 × (15 5555 5555 5555 16 × 2 −52 ) = 2 −54 × 15 5555 5555 5555 16 = 0,333333333333333314829616256247390992939472198486328125 ≈ 1/3
Velocidad de ejecución con aritmética de doble precisión
El uso de variables de coma flotante de doble precisión suele ser más lento que el de sus equivalentes de precisión simple. Un área de la computación donde esto representa un problema particular es el código paralelo que se ejecuta en GPU. Por ejemplo, al usar la plataforma CUDA de Nvidia , los cálculos con doble precisión pueden tardar, dependiendo del hardware, entre 2 y 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, seno, coseno, tangente al cuadrado, logaritmo, exponencial y raíz cuadrada) necesitan más cálculos para proporcionar resultados precisos de doble precisión y, por lo tanto, son más lentas.
Limitaciones de precisión en valores enteros
- Los números enteros desde − 2 53 hasta 2 53 ( − 9,007,199,254,740,992 hasta 9,007,199,254,740,992) se pueden representar exactamente.
- Los enteros entre 2 53 y 2 54 = 18,014,398,509,481,984 se redondean a un múltiplo de 2 (número par).
- Los enteros entre 2 54 y 2 55 = 36,028,797,018,963,968 se redondean a un múltiplo de 4.
- Los números enteros entre 2 n y 2 n +1 se redondean a un múltiplo de 2 n −52 .
Implementaciones
Los números de doble precisión se implementan de diferentes maneras en muchos lenguajes de programación. En procesadores con precisión dinámica únicamente, como los x86 sin SSE2 (o cuando no se utiliza SSE2 por motivos de compatibilidad) y con precisión extendida 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 . La precisión doble no es un requisito de los estándares (excepto en el anexo F opcional de C99 , que cubre la aritmética IEEE 754), pero en la mayoría de los sistemas, el doubletipo corresponde a precisión doble. Sin embargo, en sistemas x86 de 32 bits con precisión extendida por defecto, algunos compiladores pueden no ajustarse al estándar C o la aritmética puede sufrir de doble redondeo . [ 5 ]
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.
Lisp 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 sinónimos apropiados para los demás tipos. Common Lisp proporciona excepciones para capturar desbordamientos y subdesbordamientos de punto flotante, así como la excepción de punto flotante inexacta, según IEEE 754. El estándar ANSI no describe infinitos ni NaN; sin embargo, varias implementaciones los proporcionan como extensiones.
Java
En Java anterior a la versión 1.2, todas las implementaciones debían cumplir con la norma IEEE 754. La versión 1.2 permitió que las implementaciones incorporaran mayor precisión en los cálculos intermedios para plataformas como x87 . Por lo tanto, se introdujo el modificador strictfp para garantizar cálculos estrictos según la norma IEEE 754. La precisión de punto flotante estricta se restauró en Java 17. [ 6 ]
JavaScript
Como especifica el estándar ECMAScript , todas las operaciones aritméticas en JavaScript deben realizarse utilizando aritmética de punto flotante de doble precisión. [ 7 ]
JSON
El formato de datos JSON admite valores numéricos y no impone límites a su precisión o rango. Sin embargo, el RFC 8259 recomienda que, dado que los números binarios IEEE 754 de 64 bits están ampliamente implementados, las implementaciones de procesamiento JSON pueden lograr una buena interoperabilidad si no esperan mayor precisión o rango que el que ofrece el formato binario de 64 bits. [ 8 ]
Óxido y Zig
Notas y referencias
- ↑ William Kahan (1 de octubre de 1997). "Notas de clase sobre el estado de la norma IEEE 754 para aritmética binaria de punto flotante" (PDF) . pág. 4. Archivado (PDF) del original el 8 de febrero de 2012.
- ↑ Savard, John JG (2018) [2005], "Formatos de punto flotante" , quadibloc , archivado del original el 3 de julio de 2018 , recuperado el 16 de julio de 2018
- ↑ "pack – convierte una lista en una representación binaria" . Archivado del original el 18 de febrero de 2009. Consultado el 4 de febrero de 2009 .
- ↑ "La nueva Titan V de Nvidia ofrece 110 teraflops con un solo chip" . Tom's Hardware . 8 de diciembre de 2017. Consultado el 5 de noviembre de 2018 .
- ↑ "Error 323: el código optimizado produce resultados extraños de punto flotante" . gcc.gnu.org . Archivado del original el 30 de abril de 2018. Consultado el 30 de abril de 2018 .
- ↑ Darcy, Joseph D. "JEP 306: Restaurar la semántica de punto flotante siempre estricta" . Consultado el 12 de septiembre de 2021 .
- ↑ ECMA-262 Especificación del lenguaje ECMAScript (PDF) (5.ª ed.). Ecma International. pág. 29, §8.5 El tipo numérico . Archivado (PDF) del original el 13 de marzo de 2012.
- ↑ T. Bray (diciembre de 2017). El formato de intercambio de datos JSON (JavaScript Object Notation) . Grupo de trabajo de ingeniería de Internet . doi : 10.17487/RFC8259 . ISSN 2070-1721 . STD 90. RFC 8259 . Estándar de Internet 90.
- ↑ "Tipos de datos - El lenguaje de programación Rust" . doc.rust-lang.org . Consultado el 10 de agosto de 2024 .
- ↑ "Documentación - El lenguaje de programación Zig" . ziglang.org . Consultado el 10 de agosto de 2024 .
- Aritmética binaria
- aritmética informática
- Tipos de punto flotante