La precisión extendida se refiere a formatos de números de punto flotante que proporcionan una mayor precisión que los formatos de punto flotante básicos. [1] Los formatos de precisión extendida admiten un formato básico al minimizar los errores de redondeo y desbordamiento en valores intermedios de expresiones en el formato base. A diferencia de la precisión extendida , la aritmética de precisión arbitraria se refiere a implementaciones de tipos numéricos mucho más grandes (con un recuento de almacenamiento que generalmente no es una potencia de dos) utilizando software especial (o, raramente, hardware).
Existe una larga historia de formatos de punto flotante extendidos que se remonta a casi mediados del siglo pasado [ ¿cuándo? ] . Varios fabricantes han utilizado diferentes formatos de precisión extendida para diferentes máquinas. En muchos casos, el formato de precisión extendida no es exactamente el mismo que una ampliación de los formatos ordinarios de precisión simple y doble que se pretende ampliar. En unos pocos casos, la implementación fue simplemente un cambio basado en software en el formato de datos de punto flotante, pero en la mayoría de los casos, la precisión extendida se implementó en hardware, ya sea integrado en el propio procesador central o, más a menudo, integrado en el hardware de un procesador adjunto opcional llamado " unidad de punto flotante " (FPU) o "procesador de punto flotante" ( FPP ), accesible a la CPU como un dispositivo de entrada / salida rápido.
El IBM 1130 , vendido en 1965, [2] ofrecía dos formatos de punto flotante: un formato de "precisión estándar" de 32 bits y un formato de "precisión extendida" de 40 bits. El formato de precisión estándar contiene un mantra de complemento a dos de 24 bits , mientras que la precisión extendida utiliza un mantra de complemento a dos de 32 bits. El último formato hace un uso completo de las operaciones de números enteros de 32 bits de la CPU. La característica en ambos formatos es un campo de 8 bits que contiene la potencia de dos sesgada por 128. Las operaciones aritméticas de punto flotante se realizan por software y no se admite la precisión doble en absoluto. El formato extendido ocupa tres palabras de 16 bits, y el espacio adicional simplemente se ignora. [3]
El IBM System/360 admite un formato de punto flotante "corto" de 32 bits y un formato de punto flotante "largo" de 64 bits. [4] El 360/85 y el System/370 posterior añaden soporte para un formato "extendido" de 128 bits. [5] Estos formatos todavía se admiten en el diseño actual , donde ahora se denominan formatos de " punto flotante hexadecimal " (HFP).
El puerto Microsoft BASIC para la CPU 6502 , como en adaptaciones como Commodore BASIC , AppleSoft BASIC , KIM-1 BASIC o MicroTAN BASIC, admite una variante extendida de 40 bits del formato de punto flotante Microsoft Binary Format (MBF) desde 1977. [6]
El estándar de punto flotante IEEE 754 recomienda que las implementaciones proporcionen formatos de precisión extendidos. El estándar especifica los requisitos mínimos para un formato extendido, pero no especifica una codificación. [7] La codificación es una elección del implementador. [8]
Los procesadores IA32 , x86-64 e Itanium admiten el que es por lejos el formato más influyente en este estándar, el formato Intel de 80 bits (significado de 64 bits) "doblemente extendido", que se describe en la siguiente sección.
Los coprocesadores matemáticos Motorola 6888x y los procesadores Motorola 68040 y 68060 también admiten un formato de precisión extendida de 64 bits (similar al formato Intel, aunque rellenado a un formato de 96 bits con 16 bits no utilizados insertados entre los campos de exponente y significación, y los valores con exponente cero y bit 63 uno son valores normalizados [9] ). Los procesadores Coldfire posteriores no admiten este formato de precisión extendida de 96 bits. [10]
El coprocesador matemático FPA10 para los primeros procesadores ARM también admite un formato de precisión extendida de significando de 64 bits (similar al formato Intel, aunque rellenado a un formato de 96 bits con 16 bits cero insertados entre los campos de signo y exponente), pero sin redondeo correcto. [11]
Los formatos x87 y Motorola 68881 de 80 bits cumplen con los requisitos del formato doblemente extendido IEEE 754-1985, [12] al igual que el formato binario IEEE 754 de 128 bits .
El formato de precisión extendida x86 es un formato de 80 bits implementado por primera vez en el coprocesador matemático Intel 8087 y es compatible con todos los procesadores que se basan en el diseño x86 que incorporan una unidad de punto flotante (FPU).
El Intel 8087 fue el primer dispositivo x86 que admitió aritmética de punto flotante en hardware. Fue diseñado para admitir un formato de "precisión simple" de 32 bits y un formato de "doble precisión" de 64 bits para codificar e intercambiar números de punto flotante. El formato extendido no fue diseñado para almacenar datos con mayor precisión, sino para permitir el cálculo de resultados dobles temporales de manera más confiable y precisa al minimizar el desbordamiento y los errores de redondeo en los cálculos intermedios. [a] [14] [15] Todos los registros de punto flotante en el 8087 mantienen este formato, y convierte automáticamente los números a este formato cuando carga registros desde la memoria y también convierte los resultados nuevamente a los formatos más convencionales cuando almacena los registros nuevamente en la memoria. Para permitir que los resultados de subexpresiones intermedias se guarden en variables scratch de precisión extendida y continúen a través de declaraciones del lenguaje de programación, y que los cálculos interrumpidos se reanuden donde fueron interrumpidos, proporciona instrucciones que transfieren valores entre estos registros internos y la memoria sin realizar ninguna conversión, lo que permite el acceso al formato extendido para los cálculos [b] , lo que también revive el problema de la precisión de las funciones de dichos números, pero con una precisión mayor.
Las unidades de coma flotante (FPU) de todos los procesadores x86 posteriores han admitido este formato. Como resultado, se puede desarrollar software que aproveche la mayor precisión proporcionada por este formato. William Kahan , uno de los principales diseñadores de la aritmética x87 y la propuesta inicial del estándar IEEE 754, señala sobre el desarrollo del punto flotante x87: "Se incluyó un formato extendido tan amplio como nos atrevimos (80 bits) para que cumpliera la misma función de soporte que cumple el formato interno decimal 13 en las calculadoras decimales 10 de Hewlett-Packard". [17] Además, Kahan señala que 64 bits era el mantis más ancho a través del cual se podía realizar la propagación del acarreo sin aumentar el tiempo de ciclo en el 8087, [18] y que la precisión extendida x87 se diseñó para que fuera extensible a una mayor precisión en procesadores futuros:
Este formato de 80 bits utiliza un bit para el signo de la mantisa, 15 bits para el campo del exponente (es decir, el mismo rango que el formato IEEE 754 de precisión cuádruple de 128 bits) y 64 bits para la mantisa . El campo del exponente está sesgado por 16383, lo que significa que 16383 debe restarse del valor en el campo del exponente para calcular la potencia real de 2. [20] Se reserva un valor de campo de exponente de 32767 (los quince bits 1 ) para permitir la representación de estados especiales como infinito y Not a Number . Si el campo del exponente es cero, el valor es un número desnormalizado y el exponente de 2 es −16382. [21]
En la siguiente tabla, " s " es el valor del bit de signo (0 significa positivo, 1 significa negativo), " e " es el valor del campo de exponente interpretado como un entero positivo y " m " es la mantisa interpretada como un número binario positivo, donde el punto binario se encuentra entre los bits 63 y 62. El campo " m " es la combinación de las partes enteras y fraccionarias en el diagrama anterior.
A diferencia de los formatos de precisión simple y doble , este formato no utiliza un bit implícito u oculto . En su lugar, el bit 63 contiene la parte entera de la mantisa y los bits 62 a 0 contienen la parte fraccionaria. El bit 63 será 1 en todos los números normalizados. Este diseño tenía varias ventajas cuando se estaba desarrollando el 8087 :
El formato de punto flotante de 80 bits estaba ampliamente disponible en 1984, [25] después del desarrollo de C, Fortran y lenguajes informáticos similares, que inicialmente ofrecían solo los tamaños comunes de punto flotante de 32 y 64 bits. En el diseño x86, la mayoría de los compiladores de C ahora admiten precisión extendida de 80 bits a través del tipo long double , y esto se especificó en los estándares C99 / C11 (aritmética de punto flotante IEC 60559 (Anexo F)). Los compiladores en x86 para otros lenguajes a menudo también admiten precisión extendida, a veces a través de extensiones no estándar: por ejemplo, Turbo Pascal ofrece un extended
tipo, y varios compiladores de Fortran tienen un REAL*10
tipo (análogo a REAL*4
y ). Dichos compiladores también suelen incluir subrutinasREAL*8
matemáticas de precisión extendida , como funciones de raíz cuadrada y trigonométricas , en sus bibliotecas estándar .
El formato de punto flotante de 80 bits tiene un rango (incluidos los subnormales ) de aproximadamente 3,65 × 10 −4951 a 1,18 × 10+4932 .Aunque log 10 ( 2 64 ) ≈ 19.266 ,este formato se describe generalmente como que da aproximadamente dieciocho dígitos significativos de precisión (el piso de log 10 ( 2 63 ) ,la precisión mínima garantizada). El uso de decimal cuando se habla de binario es desafortunado porque la mayoría de las fracciones decimales son secuencias recurrentes en binario al igual que 2/3 está en decimal. Por lo tanto, un valor como 10,15 se representa en binario como equivalente a 10,1499996185 etc. en decimal paraREAL*4
pero 10,15000000000000035527 etc. enREAL*8
: la interconversión implicará aproximación, excepto para aquellas pocas fracciones decimales que representan un valor binario exacto, como 0,625 . ParaREAL*10
, la cadena decimal es 10,149999999999999996530553 etc. El último 9 dígito es el decimoctavo dígito fraccionario y, por lo tanto, el vigésimo dígito significativo de la cadena. Los límites de conversión entre decimal y binario para el formato de 80 bits se pueden dar de la siguiente manera: si una cadena decimal con un máximo de 18 dígitos significativos se redondea correctamente a un valor de punto flotante binario IEEE 754 de 80 bits (como en la entrada) y luego se convierte nuevamente al mismo número de dígitos decimales significativos (como para la salida), entonces la cadena final coincidirá exactamente con el original; mientras que, a la inversa, si un valor de punto flotante binario IEEE 754 de 80 bits se convierte correctamente y (lo más cercano) se redondea a una cadena decimal con al menos 21 dígitos decimales significativos y luego se convierte nuevamente a formato binario, coincidirá exactamente con el original. [12] Estas aproximaciones son particularmente problemáticas cuando se especifica el mejor valor para constantes en fórmulas con alta precisión, como podría calcularse mediante aritmética de precisión arbitraria .
Un ejemplo notable de la necesidad de un mínimo de 64 bits de precisión en el significado del formato de precisión extendida es la necesidad de evitar la pérdida de precisión al realizar la exponenciación en valores de doble precisión . [26] [27] [28] [c] Las unidades de punto flotante x86 no proporcionan una instrucción que realice directamente la exponenciación : en su lugar, proporcionan un conjunto de instrucciones que un programa puede usar en secuencia para realizar la exponenciación utilizando la ecuación:
Para evitar la pérdida de precisión, los resultados intermedios " log 2 ( x ) " y " y ·log 2 ( x ) " deben calcularse con mucha mayor precisión, porque efectivamente tanto el campo de exponente como el de mantisa de x deben encajar en el campo de mantisa del resultado intermedio. Posteriormente, el campo de mantisa del resultado intermedio se divide entre los campos de exponente y mantisa del resultado final cuando se calcula el resultado intermedio 2 . La siguiente discusión describe este requisito con más detalle.
Con un poco de análisis, un valor de doble precisión IEEE 754 se puede representar como:
donde s es el signo del exponente (ya sea 0 o 1), E es el exponente no sesgado, que es un número entero que va de 0 a 1023, y M es la mantisa, que es un valor de 53 bits que cae en el rango 1 ≤ M < 2. Los números negativos y el cero se pueden ignorar porque el logaritmo de estos valores no está definido. Para los propósitos de esta discusión, M no tiene 53 bits de precisión porque está restringido a ser mayor o igual a uno, es decir, el bit oculto no cuenta para la precisión (Note que en situaciones donde M es menor que 1, el valor es en realidad un desnormalizado y por lo tanto puede haber sufrido ya pérdida de precisión. Esta situación está más allá del alcance de este artículo).
Tomando el logaritmo de esta representación de un número de doble precisión y simplificando el resultado es lo siguiente:
Este resultado demuestra que al tomar el logaritmo en base 2 de un número, el signo del exponente del valor original se convierte en el signo del logaritmo, el exponente del valor original se convierte en la parte entera del significado del logaritmo, y el significado del valor original se transforma en la parte fraccionaria del significado del logaritmo.
Como E es un número entero en el rango de 0 a 1023, se necesitan hasta 10 bits a la izquierda del punto de la base para representar la parte entera del logaritmo. Como M cae en el rango 1 ≤ M < 2 , el valor de log 2 M caerá en el rango 0 ≤ log 2 M < 1 , por lo que se necesitan al menos 52 bits a la derecha del punto de la base para representar la parte fraccionaria del logaritmo. La combinación de 10 bits a la izquierda del punto de la base con 52 bits a la derecha del punto de la base significa que la parte mantisa del logaritmo debe calcularse con al menos 62 bits de precisión. En la práctica, los valores de M menores que requieren 53 bits a la derecha del punto de la base y los valores de M menores que requieren 54 bits a la derecha del punto de la base para evitar la pérdida de precisión. Para equilibrar este requisito de mayor precisión a la derecha del punto de la base, los exponentes menores a 512 solo requieren 9 bits a la izquierda del punto de la base y los exponentes menores a 256 requieren solo 8 bits a la izquierda del punto de la base.
La parte final del cálculo de la exponenciación es el cálculo de 2 resultados intermedios . El "resultado intermedio" consiste en una parte entera " I " sumada a una parte fraccionaria " F ". Si el resultado intermedio es negativo, se necesita un pequeño ajuste para obtener una parte fraccionaria positiva porque tanto " I " como " F " son números negativos.
Para obtener resultados intermedios positivos:
Para resultados intermedios negativos:
De esta forma, la parte entera del resultado intermedio (" I " o " I − 1 ") más un sesgo se convierte en el exponente del resultado final y la parte fraccionaria positiva transformada del resultado intermedio: 2 F o 2 F + 1 se convierte en el significado del resultado final. Para proporcionar 52 bits de precisión al resultado final, la parte fraccionaria positiva debe mantenerse en al menos 52 bits.
En conclusión, la cantidad exacta de bits de precisión necesarios en la significancia del resultado intermedio depende en cierta medida de los datos, pero 64 bits son suficientes para evitar la pérdida de precisión en la gran mayoría de los cálculos de exponenciación que involucran números de doble precisión .
La cantidad de bits necesarios para el exponente del formato de precisión extendida se deriva del requisito de que el producto de dos números de precisión doble no debe desbordarse cuando se calcula utilizando el formato extendido. El exponente más grande posible de un valor de precisión doble es 1023, por lo que el exponente del producto más grande posible de dos números de precisión doble es 2047 (un valor de 11 bits). Agregar un sesgo para tener en cuenta los exponentes negativos significa que el campo de exponentes debe tener al menos 12 bits de ancho.
La combinación de estos requisitos: 1 bit para el signo, 12 bits para el exponente sesgado y 64 bits para la mantisa significa que el formato de precisión extendida necesitaría al menos 77 bits. Las consideraciones de ingeniería dieron como resultado la definición final del formato de 80 bits (en particular, el estándar IEEE 754 requiere que el rango de exponentes de un formato de precisión extendida coincida con el del siguiente formato de precisión más grande, quad , que es de 15 bits). [27]
Otro ejemplo de cálculos que se benefician de la aritmética de precisión extendida son los esquemas de refinamiento iterativo , utilizados para limpiar indirectamente los errores acumulados en la solución directa durante la cantidad típicamente muy grande de cálculos realizados para el álgebra lineal numérica. [30]
long double
el uso de números de punto flotante de 80 bits en sistemas x86. Sin embargo, este es un comportamiento definido por la implementación y no es obligatorio, pero está permitido por el estándar, como se especifica para el hardware IEEE 754 en el estándar C99 "Anexo F IEC 60559 aritmética de punto flotante". GCC también proporciona __float80
y __float128
tipos. [31]long-float
el uso de números de punto flotante de 80 bits en sistemas x86.real
implementa el uso del tamaño de punto flotante más grande implementado en hardware, por ejemplo, 80 bits para CPU x86 . En otras máquinas, este será el tipo de punto flotante más amplio compatible de forma nativa con la CPU, o 64 bits de precisión doble, lo que sea más amplio.extended
tipo de 80 bits disponible además de real
/ single
(32 bits) y double
(64 bits), ya sea de forma nativa (cuando hay un coprocesador 80x87) o emulado (a través de la biblioteca Turbo87); este extended
tipo está disponible en plataformas de 16, 32 y 64 bits, posiblemente con relleno . [32]Float80
tipo de datos.EXT
un EXTENDED
tipo de datos de punto flotante de precisión extendida de 10 bytes.