La aritmética de coma flotante decimal ( DFP ) se refiere tanto a una representación como a las operaciones en números de coma flotante decimal . Trabajar directamente con fracciones decimales (base 10) puede evitar los errores de redondeo que normalmente ocurren al convertir fracciones decimales (comunes en datos ingresados por humanos, como medidas o información financiera) y fracciones binarias (base 2).
La ventaja de la representación decimal de coma flotante sobre la representación decimal de coma fija y la representación entera es que admite un rango de valores mucho más amplio. Por ejemplo, mientras que una representación de coma fija que asigna 8 dígitos decimales y 2 posiciones decimales puede representar los números 123456.78, 8765.43, 123.00, etc., una representación de coma flotante con 8 dígitos decimales también podría representar 1.2345678, 1234567.8, 0.000012345678 12345678000000000 y así sucesivamente. Este rango más amplio puede ralentizar drásticamente la acumulación de errores de redondeo durante cálculos sucesivos; por ejemplo, el algoritmo de suma de Kahan se puede utilizar en coma flotante para sumar muchos números sin acumulación asintótica de error de redondeo.
Implementaciones
Los primeros usos mecánicos de punto flotante decimal son evidentes en el ábaco , la regla de cálculo , la calculadora Smallwood , y algunas otras calculadoras que las entradas de apoyo en notación científica . En el caso de las calculadoras mecánicas, el exponente a menudo se trata como información complementaria que se contabiliza por separado.
La computadora IBM 650 admitía un formato decimal de coma flotante de 8 dígitos en 1953. [1] La máquina Wang VS, por lo demás binaria , admitía un formato decimal de coma flotante de 64 bits en 1977. [2] La biblioteca de soporte de coma flotante para el El procesador Motorola 68040 proporcionó un formato de almacenamiento decimal de coma flotante de 96 bits en 1990. [2]
Algunos lenguajes de computadora tienen implementaciones de aritmética de coma flotante decimal, incluyendo PL / I , C # , Java con decimal grande, emacs con calc y el módulo decimal de Python . En 1987, IEEE lanzó IEEE 854 , un estándar para computación con coma flotante decimal, que carecía de una especificación sobre cómo los datos de coma flotante deberían codificarse para el intercambio con otros sistemas. Esto se abordó posteriormente en IEEE 754-2008 , que estandarizó la codificación de datos de coma flotante decimal, aunque con dos métodos alternativos diferentes.
IBM POWER6 y los procesadores POWER más nuevos incluyen DFP en el hardware, al igual que IBM System z9 [3] (y máquinas posteriores zSeries). SilMinds ofrece SilAx, un coprocesador DFP vectorial configurable . [4] IEEE 754-2008 define esto con más detalle. Fujitsu también tiene procesadores Sparc de 64 bits con DFP en hardware. [5] [2]
Codificación IEEE 754-2008
El estándar IEEE 754-2008 define representaciones de coma flotante decimal de 32, 64 y 128 bits. Al igual que los formatos binarios de coma flotante, el número se divide en un signo, un exponente y un significando . A diferencia del punto flotante binario, los números no están necesariamente normalizados; los valores con pocos dígitos significativos tienen múltiples representaciones posibles: 1 × 10 2 = 0.1 × 10 3 = 0.01 × 10 4 , etc. Cuando el significando es cero, el exponente puede ser cualquier valor.
decimal32 | decimal64 | decimal128 | decimal (32 k ) | Formato |
---|---|---|---|---|
1 | 1 | 1 | 1 | Campo de signo (bits) |
5 | 5 | 5 | 5 | Campo de combinación (bits) |
6 | 8 | 12 | w = 2 × k + 4 | Campo de continuación de exponente (bits) |
20 | 50 | 110 | t = 30 × k −10 | Campo de continuación del coeficiente (bits) |
32 | 64 | 128 | 32 × k | Tamaño total (bits) |
7 | dieciséis | 34 | p = 3 × t / 10 + 1 = 9 × k −2 | Tamaño del coeficiente (dígitos decimales) |
192 | 768 | 12288 | 3 × 2 w = 48 × 4 k | Rango de exponente |
96 | 384 | 6144 | Emáx = 3 × 2 w −1 | El valor más grande es 9,99 ... × 10 Emax |
−95 | −383 | −6143 | Emín = 1 − Emáx | El valor normalizado más pequeño es 1,00 ... × 10 Emin |
−101 | −398 | −6176 | Etiny = 2 − p − Emáx | El valor más pequeño distinto de cero es 1 × 10 Etiny |
Los rangos de exponentes se eligieron de modo que el rango disponible para los valores normalizados sea aproximadamente simétrico. Dado que esto no se puede hacer exactamente con un número par de posibles valores de exponente, el valor extra se le dio a Emax.
Se definen dos representaciones diferentes:
- Uno con un campo de significado entero binario codifica el significado como un entero binario grande entre 0 y 10 p −1. Se espera que esto sea más conveniente para las implementaciones de software que utilizan una ALU binaria .
- Otro con un campo de significado decimal densamente empaquetado codifica dígitos decimales de manera más directa. Esto hace que la conversión hacia y desde la forma de punto flotante binario sea más rápida, pero requiere hardware especializado para manipular de manera eficiente. Se espera que esto sea más conveniente para las implementaciones de hardware.
Ambas alternativas proporcionan exactamente el mismo rango de valores representables.
Los dos bits más significativos del exponente están limitados al rango de 0−2, y los 4 bits más significativos del significando están limitados al rango de 0−9. Las 30 combinaciones posibles se codifican en un campo de 5 bits, junto con formas especiales para infinito y NaN .
Si los 4 bits más significativos del significando están entre 0 y 7, el valor codificado comienza de la siguiente manera:
s 00mmm xxx El exponente comienza con 00, significando con 0mmms 01mmm xxx El exponente comienza con 01, significando con 0mmms 10 mmm xxx El exponente comienza con 10, significando con 0 mmm
Si los 4 bits iniciales del significado son binarios 1000 o 1001 (decimal 8 o 9), el número comienza de la siguiente manera:
s 1100m xxx El exponente comienza con 00, lo que significa 100ms 1101m xxx El exponente comienza con 01, lo que significa 100ms 1110m xxx El exponente comienza con 10, lo que significa 100m
El bit inicial (s en el anterior) es un bit de signo, y los siguientes bits (xxx en el anterior) codifican los bits de exponentes adicionales y el resto del dígito más significativo, pero los detalles varían según la alternativa de codificación utilizada.
Las combinaciones finales se utilizan para infinitos y NaN, y son las mismas para ambas codificaciones alternativas:
s 11110 x ± Infinito (consulte la recta numérica real extendida )s 11111 0 silencioso NaN (bit de signo ignorado)s 11111 1 señalización NaN (bit de signo ignorado)
En los últimos casos, se ignoran todos los demás bits de la codificación. Por lo tanto, es posible inicializar una matriz a NaN llenándola con un valor de un solo byte.
Campo de significado de entero binario
Este formato usa un significado binario de 0 a 10 p −1. Por ejemplo, el Decimal32 significand puede ser de hasta 10 7 -1 = 9 999 999 = 98967F 16 = 1001 1000100101 1001111111 2 . Si bien la codificación puede representar significados más grandes, son ilegales y el estándar requiere implementaciones para tratarlos como 0, si se encuentran en la entrada.
Como se describió anteriormente, la codificación varía dependiendo de si los 4 bits más significativos del significando están en el rango de 0 a 7 (0000 2 a 0111 2 ), o superior (1000 2 o 1001 2 ).
Si los 2 bits después del bit de signo son "00", "01" o "10", entonces el campo de exponente consta de los 8 bits que siguen al bit de signo (los 2 bits mencionados más 6 bits del "campo de continuación del exponente") , y el significado son los 23 bits restantes, con un bit 0 al principio implícito, que se muestra aquí entre paréntesis:
s 00eeeeee (0) ttt tttttttttt tttttttttt s 01eeeeee (0) ttt tttttttttt tttttttttt s 10eeeeee (0) ttt tttttttttt tttttttttt
Esto incluye números subnormales donde el primer dígito significativo es 0.
Si los 2 bits después del bit de signo son "11", entonces el campo exponente de 8 bits se desplaza 2 bits a la derecha (después del bit de signo y los bits "11" a partir de entonces), y el significado representado está en el resto 21 bits. En este caso, hay una secuencia inicial de 3 bits "100" implícita (es decir, no almacenada) en el verdadero significado:
s 1100eeeeee (100) t tttttttttt tttttttttt s 1101eeeeee (100) t tttttttttt tttttttttt s 1110eeeeee (100) t tttttttttt tttttttttt
La secuencia de 2 bits "11" después del bit de signo indica que hay un prefijo de 3 bits "100" implícito en el significado.
Tenga en cuenta que los bits iniciales del campo de significado no codifican el dígito decimal más significativo; son simplemente parte de un número binario puro más grande. Por ejemplo, un significado de 8 000 000 se codifica como binario 0111 1010000100 1000000000 , con los 4 bits iniciales codificando 7; el primer significado que requiere un bit 24 (y por lo tanto la segunda forma de codificación) es 2 23 = 8 388 608 .
En los casos anteriores, el valor representado es:
- (−1) signo × 10 exponente − 101 × significando
Decimal64 y Decimal128 operan de manera análoga, pero con campos de continuación y significado de exponente más grandes. Para Decimal128, la segunda forma de codificación en realidad nunca se usa; el mayor significado válido de 10 34 −1 = 1ED09BEAD87C0378D8E63FFFFFFFF 16 se puede representar en 113 bits.
Campo de significado decimal densamente empaquetado
En esta versión, el significado se almacena como una serie de dígitos decimales. El dígito inicial está entre 0 y 9 (3 o 4 bits binarios), y el resto del significado utiliza la codificación decimal densamente empaquetada (DPD).
Los 2 bits iniciales del exponente y el dígito inicial (3 o 4 bits) del significando se combinan en los cinco bits que siguen al bit de signo. A esto le sigue un campo de continuación de exponente de desplazamiento fijo.
Finalmente, el campo de continuación del significado está compuesto por 2, 5 u 11 declives de 10 bits , cada uno de los cuales codifica 3 dígitos decimales. [7]
Si los dos primeros bits después del bit de signo son "00", "01" o "10", entonces esos son los bits iniciales del exponente y los tres bits posteriores se interpretan como el dígito decimal inicial (0 a 7 ): [8]
Peine. Exponente Significativo s 00 TTT (00) eeeeee (0TTT) [tttttttttt] [tttttttttt] s 01 TTT (01) eeeeee (0TTT) [tttttttttt] [tttttttttt] s 10 TTT (10) eeeeee (0TTT) [tttttttttt] [tttttttttt]
Si los dos primeros bits después del bit de signo son "11", los segundos dos bits son los bits iniciales del exponente y el último bit tiene el prefijo "100" para formar el dígito decimal inicial (8 o 9):
Peine. Exponente Significativo s 1100 T (00) eeeeee (100T) [tttttttttt] [tttttttttt] s 1101 T (01) eeeeee (100T) [tttttttttt] [tttttttttt] s 1110 T (10) eeeeee (100T) [tttttttttt] [tttttttttt]
Las dos combinaciones restantes (11110 y 11111) del campo de 5 bits se utilizan para representar ± infinito y NaN, respectivamente.
Operaciones aritméticas de coma flotante
La regla habitual para realizar aritmética de punto flotante es que se calcula el valor matemático exacto, [9] y luego el resultado se redondea al valor representable más cercano en la precisión especificada. De hecho, este es el comportamiento exigido para el hardware informático compatible con IEEE, en condiciones normales de redondeo y en ausencia de condiciones excepcionales.
Para facilitar la presentación y la comprensión, se utilizará precisión de 7 dígitos en los ejemplos. Los principios fundamentales son los mismos en cualquier precisión.
Adición
Un método simple para sumar números de punto flotante es primero representarlos con el mismo exponente. En el siguiente ejemplo, el segundo número se desplaza a la derecha en 3 dígitos. Procedemos con el método de adición habitual:
El siguiente ejemplo es decimal, lo que simplemente significa que la base es 10.
123456.7 = 1,234567 × 10 5 101,7654 = 1,017654 × 10 2 = 0,001017654 × 10 5
Por eso:
123456.7 + 101.7654 = (1.234567 × 10 5 ) + (1.017654 × 10 2 ) = (1.234567 × 10 5 ) + (0.001017654 × 10 5 ) = 10 5 × (1,234567 + 0,001017654) = 10 5 × 1,235584654
Esto no es más que convertirlo a notación científica . En detalle:
e = 5; s = 1,234567 (123456,7)+ e = 2; s = 1.017654 (101.7654)
e = 5; s = 1,234567+ e = 5; s = 0,001017654 (después de cambiar)-------------------- e = 5; s = 1.235584654 (suma verdadera: 123558.4654)
Este es el resultado verdadero, la suma exacta de los operandos. Se redondeará a 7 dígitos y luego se normalizará si es necesario. El resultado final es:
e = 5; s = 1.235585 (suma final: 123558.5)
Tenga en cuenta que los 3 dígitos bajos del segundo operando (654) se pierden esencialmente. Este es un error de redondeo . En casos extremos, la suma de dos números distintos de cero puede ser igual a uno de ellos:
e = 5; s = 1,234567+ e = −3; s = 9,876543
e = 5; s = 1,234567+ e = 5; s = 0,00000009876543 (después del cambio)---------------------- e = 5; s = 1.23456709876543 (suma verdadera) e = 5; s = 1.234567 (después del redondeo / normalización)
Otro problema de pérdida de significación ocurre cuando se restan dos números cercanos. e = 5; s = 1,234571 ye = 5; s = 1.234567 son representaciones de los racionales 123457.1467 y 123456.659.
e = 5; s = 1,234571- e = 5; s = 1,234567---------------- e = 5; s = 0,000004 e = −1; s = 4,000000 (después del redondeo / normalización)
La mejor representación de esta diferencia es e = −1; s = 4.877000, que difiere más del 20% de e = −1; s = 4,000000. En casos extremos, el resultado final puede ser cero, aunque un cálculo exacto puede ser de varios millones. Esta cancelación ilustra el peligro de asumir que todos los dígitos de un resultado calculado son significativos.
El tratamiento de las consecuencias de estos errores son temas de análisis numérico .
Multiplicación
Para multiplicar se multiplican los significados, se suman los exponentes y se redondea y normaliza el resultado.
e = 3; s = 4.734612× e = 5; s = 5,417242----------------------- e = 8; s = 25.648538980104 (producto verdadero) e = 8; s = 25,64854 (después del redondeo) e = 9; s = 2.564854 (después de la normalización)
La división se realiza de manera similar, pero eso es más complicado.
No hay problemas de cancelación o absorción con la multiplicación o la división, aunque se pueden acumular pequeños errores a medida que las operaciones se realizan repetidamente. En la práctica, la forma en que se llevan a cabo estas operaciones en lógica digital puede ser bastante compleja.
Ver también
- Decimal codificado en binario (BCD)
Referencias
- ↑ Beebe, Nelson HF (22 de agosto de 2017). "Capítulo H. Arquitecturas históricas de punto flotante". El manual de computación de funciones matemáticas - Programación usando la biblioteca de software portátil MathCW (1 ed.). Salt Lake City, UT, Estados Unidos: Springer International Publishing AG . pag. 948. doi : 10.1007 / 978-3-319-64110-2 . ISBN 978-3-319-64109-6. LCCN 2017947446 .
- ^ a b c Savard, John JG (2018) [2007]. "El estándar de coma flotante decimal" . quadibloc . Archivado desde el original el 3 de julio de 2018 . Consultado el 16 de julio de 2018 .
- ^ "IBM z9 EC y z9 BC: mayor valor para todos" (PDF) . 306.ibm.com . Consultado el 7 de julio de 2018 .
- ^ "IP aritméticas para aplicaciones financieras - SilMinds" . Silminds.com .
- ^ "Capítulo 4. Formatos de datos". Especificación Sparc64 X / X + . Nakahara-ku, Kawasaki, Japón. Enero de 2015. p. 13.
- ^ "Punto flotante decimal en .NET" . Yoda.arachsys.com .
- ^ Muller, Jean-Michel; Brisebarre, Nicolás; de Dinechin, Florent; Jeannerod, Claude-Pierre; Lefèvre, Vincent; Melquiond, Guillaume; Revol, Nathalie; Stehlé, Damien; Torres, Serge (2010). Manual de aritmética de coma flotante (1 ed.). Birkhäuser . doi : 10.1007 / 978-0-8176-4705-6 . ISBN 978-0-8176-4704-9. LCCN 2009939668 .
- ^ Especificación de codificación decimal, versión 1.00 , de IBM
- ^ El hardware de la computadora no calcula necesariamente el valor exacto; simplemente tiene que producir el resultado redondeado equivalente como si hubiera calculado el resultado infinitamente preciso.
Otras lecturas
- Decimal Floating-Point: Algorism for Computers , Proceedings of the 16th IEEE Symposium on Computer Arithmetic ( Cowlishaw, Mike F. , 2003)