Formato de punto flotante de doble precisión

Formato de número de computadora de 64 bits

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 generalmente 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 elegir la precisión doble cuando el rango o la precisión de la precisión simple serían insuficientes.

En el estándar IEEE 754 , el formato base 2 de 64 bits se conoce oficialmente como binary64 ; se lo llamó double en IEEE 754-1985 . IEEE 754 especifica formatos de punto flotante adicionales, incluida la precisión simple 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 requerida ] 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 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 precisión doble es un formato que se utiliza con frecuencia en las PC, debido a su mayor rango que el de punto flotante de precisión simple, a pesar de su rendimiento y costo de ancho de banda. Se lo conoce comúnmente simplemente como double . 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 mantis 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 un máximo de 15 dígitos significativos se convierte al formato de doble precisión IEEE 754, lo que da como resultado un número normal, y luego se convierte nuevamente 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 a una cadena decimal con al menos 17 dígitos significativos y luego se convierte nuevamente a una representación de doble precisión, el resultado final debe coincidir con el número original. [1]

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 exponentes a continuación). Con los 52 bits de la mantisa de fracción (F) que aparecen 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 distribuyen de la siguiente manera:

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

( 1 ) sign ( 1. b 51 b 50 . . . b 0 ) 2 × 2 e 1023 {\displaystyle (-1)^{\text{sign}}(1.b_{51}b_{50}...b_{0})_{2}\times 2^{e-1023}}

o

( 1 ) sign ( 1 + i = 1 52 b 52 i 2 i ) × 2 e 1023 {\displaystyle (-1)^{\text{sign}}\left(1+\sum _{i=1}^{52}b_{52-i}2^{-i}\right)\times 2^{e-1023}}

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 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 . Por lo tanto, el error de redondeo relativo máximo al redondear un número al número representable más cercano (la épsilon de 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 total 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 de exponentes

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

y = = =1:00000000001200116 2 1 1023 = 2 1022 {\displaystyle 2^{1-1023}=2^{-1022}} (exponente más pequeño para números normales )
y = = =1023:0111111111123ff16 2 1023 1023 = 2 0 {\displaystyle 2^{1023-1023}=2^{0}} (desplazamiento cero)
y = = =1029:10000000101240516 2 1029 1023 = 2 6 {\displaystyle 2^{1029-1023}=2^{6}}
y = = =2046:1111111111027fe16 2 2046 1023 = 2 1023 {\displaystyle 2^{2046-1023}=2^{1023}} (máximo exponente)

Los exponentes y tienen un significado especial:000167ff16

donde F es la parte fraccionaria del significado . Todos los patrones de bits son codificaciones válidas.

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

( 1 ) sign × 2 e 1023 × 1. fraction {\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 ) sign × 2 1 1023 × 0. fraction = ( 1 ) sign × 2 1022 × 0. fraction {\displaystyle (-1)^{\text{sign}}\times 2^{1-1023}\times 0.{\text{fraction}}=(-1)^{\text{sign}}\times 2^{-1022}\times 0.{\text{fraction}}}

Endianidad

Aunque muchos procesadores utilizan el almacenamiento little-endian para todos los tipos de datos (enteros, coma flotante), hay varias arquitecturas de hardware en las que los números de coma flotante se representan en forma big-endian, mientras que los enteros se representan en forma little-endian. [2] Hay procesadores ARM que tienen una representación de coma 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 coma flotante sin una representación estándar de red para ellos, el estándar XDR utiliza el IEEE 754 big-endian como su representación. Por lo tanto, puede parecer extraño que el estándar de coma flotante IEEE 754, ampliamente extendido , no especifique el orden de bytes. [3] Teóricamente, esto significa que incluso los datos de coma flotante IEEE estándar escritos por una máquina podrían no ser legibles por otra. Sin embargo, en las computadoras estándar modernas (es decir, que implementan IEEE 754), se puede asumir con seguridad que el orden de bytes es el mismo para los números de punto flotante que para los números enteros, lo que hace que la conversión sea sencilla independientemente del tipo de datos. Sin embargo, los sistemas integrados pequeños que utilizan formatos especiales de punto flotante pueden ser otra cosa.

Ejemplos de doble precisión

0 01111111111 000000000000000000000000000000000000000000000000000000 2 ≙ 3FF0 0000 0000 0000 16 ≙ +2 0 × 1 = 1
0 01111111111 0000000000000000000000000000000000000000000000000000001 2 ≙ 3FF0 0000 0000 0001 16 ≙ +2 0 × (1 + 2 −52 ) ≈ 1.000000000000002, el número más pequeño > 1
0 01111111111 000000000000000000000000000000000000000000000000000010 2 ≙ 3FF0 0000 0000 0002 16 ≙ +2 0 × (1 + 2 −51 ) ≈ 1,000000000000004
0 10000000000 0000000000000000000000000000000000000000000000000000 2 ≙ 4000 0000 0000 0000 16 ≙ +2 1 × 1 = 2
1 10000000000 00000000000000000000000000000000000000000000000000000 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 011100000000000000000000000000000000000000000000000 2 4037 0000 0000 0000 16 ≙ +2 4 × 1,0111 2 = 10111 = 23
0 01111111000 100000000000000000000000000000000000000000000000000 2 ≙ 3F88 0000 0000 0000 16 ≙ +2 −7 × 1,1 2 = 0,00000011 2 = 0,01171875 (3/256)
0 00000000000 0000000000000000000000000000000000000000000000000000001 2 ≙ 0000 0000 0000 0001 16 ≙ +2 −1022 × 2 −52 = 2 −1074 ≈ 4,9406564584124654 × 10 −324 (Mín. doble positivo subnormal)
0 00000000000 11111111111111111111111111111111111111111111111111111 2 ≙ 000F FFFF FFFF FFFF 16 ≙ +2 −1022 × (1 − 2 −52 ) ≈ 2,2250738585072009 × 10 −308 (máximo doble subnormal)
0 00000000001 000000000000000000000000000000000000000000000000000000 2 ≙ 0010 0000 0000 0000 16 ≙ +2 −1022 × 1 ≈ 2,2250738585072014 × 10 −308 (mín. doble positivo normal)
0 11111111110 11111111111111111111111111111111111111111111111111111 2 ≙ 7FEF FFFF FFFF FFFF 16 ≙ +2 1023 × (1 + (1 − 2 −52 )) ≈ 1,7976931348623157 × 10 308 (Máx. doble)
0 00000000000 0000000000000000000000000000000000000000000000000000 2 ≙ 0000 0000 0000 0000 16 ≙ +0
1 00000000000 0000000000000000000000000000000000000000000000000000 2 ≙ 8000 0000 0000 0000 16 ≙ −0
0 11111111111 000000000000000000000000000000000000000000000000000000 2 ≙ 7FF0 0000 0000 0000 16 ≙ +∞ (infinito positivo)
1 11111111111 000000000000000000000000000000000000000000000000000000 2 ≙ FFF0 0000 0000 0000 16 ≙ −∞ (infinito negativo)
0 11111111111 0000000000000000000000000000000000000000000000000000001 2 ≙ 7FF0 0000 0000 0001 16 ≙ NaN (sNaN en la mayoría de los procesadores, como x86 y ARM)
0 11111111111 100000000000000000000000000000000000000000000000000000001 2 ≙ 7FF8 0000 0000 0001 16 ≙ NaN (qNaN en la mayoría de los procesadores, como x86 y ARM)
0 11111111111 1111111111111111111111111111111111111111111111111111 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 ) ≈ 1/3
0 10000000000 1001001000011111101101010100010001000010110100011000 2 = 4009 21FB 5444 2D18 16 ≈ pi

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 , utilizan el bit más significativo del campo de significando 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.

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

Más detalladamente:

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

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

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 es un problema particular es el código paralelo que se ejecuta en GPU. Por ejemplo, al utilizar la plataforma CUDA de NVIDIA , los cálculos con doble precisión pueden tardar, según el hardware, entre 2 y 32 veces más en completarse en comparación con los que se realizan 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.

Limitaciones de precisión en valores enteros

  • Los números enteros de −2,53 a 2,53 ( −9.007.199.254.740.992 a 9.007.199.254.740.992) se pueden representar con exactitud.
  • Números enteros entre 2,53 y 2,54 = 18.014.398.509.481.984 redondeados a un múltiplo de 2 (número par).
  • Números enteros entre 2,54 y 2,55 = 36.028.797.018.963.968 redondeados 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 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 utiliza 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 precisión doble (excepto 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 x86 de 32 bits con precisión extendida por defecto, algunos compiladores pueden no cumplir con el estándar C o la aritmética puede sufrir redondeo doble . [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.

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 demás tipos como sinónimos apropiados. Common Lisp proporciona excepciones para detectar desbordamientos y subdesbordamientos de punto flotante, y la excepción de punto 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, todas las implementaciones debían cumplir con el estándar 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 strictfp para aplicar cálculos IEEE 754 estrictos. El punto flotante estricto se ha restaurado en Java 17. [6]

JavaScript

Como lo especifica el estándar ECMAScript , toda la aritmética en JavaScript se realizará utilizando aritmética de punto flotante de doble precisión. [7]

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, la RFC 8259 advierte que, dado que los números de IEEE 754 binary64 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 binary64. [8]

Óxido y Zig

Rust y Zig tienen el f64tipo de datos. [9] [10]

Notas y referencias

  1. ^ William Kahan (1 de octubre de 1997). "Lecture Notes on the Status of IEEE Standard 754 for Binary Floating-Point Arithmetic" (PDF) . pág. 4. Archivado (PDF) desde el original el 8 de febrero de 2012.
  2. ^ Savard, John JG (2018) [2005], "Formatos de punto flotante", quadibloc , archivado desde el original el 2018-07-03 , consultado el 2018-07-16
  3. ^ "pack – convierte una lista en una representación binaria". Archivado desde el original el 18 de febrero de 2009. Consultado el 4 de febrero de 2009 .
  4. ^ "El nuevo Titan V de Nvidia genera 110 teraflops con un solo chip". Tom's Hardware . 2017-12-08 . Consultado el 2018-11-05 .
  5. ^ "Error 323: el código optimizado da resultados de punto flotante extraños". gcc.gnu.org . Archivado desde el original el 30 de abril de 2018 . Consultado el 30 de abril de 2018 .
  6. ^ Darcy, Joseph D. "JEP 306: Restaurar la semántica de punto flotante siempre estricta" . Consultado el 12 de septiembre de 2021 .
  7. ^ ECMA-262 Especificación del lenguaje ECMAScript (PDF) (5.ª ed.). Ecma International. pág. 29, §8.5 El tipo de número . Archivado (PDF) desde el original el 13 de marzo de 2012.
  8. ^ "El formato de intercambio de datos de notación de objetos JavaScript (JSON)". Grupo de trabajo de ingeniería de Internet. Diciembre de 2017. Consultado el 1 de febrero de 2022 .
  9. ^ "Tipos de datos: el lenguaje de programación Rust". doc.rust-lang.org . Consultado el 10 de agosto de 2024 .
  10. ^ "Documentación - El lenguaje de programación Zig". ziglang.org . Consultado el 10 de agosto de 2024 .
Retrieved from "https://en.wikipedia.org/w/index.php?title=Double-precision_floating-point_format&oldid=1250530516"