La aritmética de punto flotante decimal ( DFP ) se refiere tanto a la representación como a las operaciones con números decimales de punto flotante . Trabajar directamente con fracciones decimales (base 10) puede evitar los errores de redondeo que suelen ocurrir al convertir entre fracciones decimales (comunes en datos ingresados por personas, como mediciones o información financiera) y fracciones binarias (base 2).
La ventaja de la representación decimal en coma flotante sobre la representación decimal en coma fija y la representación entera es que admite un rango mucho más amplio de valores. Por ejemplo, mientras que una representación en coma fija que asigna 8 dígitos decimales y 2 lugares decimales puede representar los números 123456.78, 8765.43, 123.00, etc., una representación en coma flotante con 8 dígitos decimales también podría representar 1.2345678, 1234567.8, 0.000012345678, 12345678000000000, etc. Este rango más amplio puede reducir 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 errores de redondeo.
Los primeros usos mecánicos del punto flotante decimal son evidentes en el ábaco , la regla de cálculo , la calculadora Smallwood y algunas otras calculadoras que admiten entradas en notación científica . En el caso de las calculadoras mecánicas, el exponente se suele tratar como información secundaria que se contabiliza por separado.
La computadora IBM 650 admitió un formato de punto flotante decimal de 8 dígitos en 1953. [1] La máquina Wang VS, que de otro modo sería binaria, admitió un formato de punto flotante decimal de 64 bits en 1977. [2] El Motorola 68881 admitió un formato con 17 dígitos de mantisa y 3 de exponente en 1984, y la biblioteca de soporte de punto flotante para el procesador Motorola 68040 proporcionó un formato de almacenamiento de punto flotante decimal compatible de 96 bits en 1990. [2]
Algunos lenguajes de programación tienen implementaciones de aritmética decimal de punto flotante, incluyendo PL/I , .NET , [3] emacs con calc y el módulo decimal de Python . [4] En 1987, el IEEE publicó IEEE 854 , un estándar para computación con punto flotante decimal, que carecía de una especificación sobre cómo se debían codificar los datos de punto flotante para el intercambio con otros sistemas. Esto se abordó posteriormente en IEEE 754-2008 , que estandarizó la codificación de datos de punto flotante decimal, aunque con dos métodos alternativos diferentes.
Los procesadores IBM POWER6 y los más nuevos POWER incluyen DFP en el hardware, al igual que el IBM System z9 [5] (y las máquinas zSeries posteriores). SilMinds ofrece SilAx, un coprocesador DFP vectorial configurable . [6] La norma IEEE 754-2008 lo define con más detalle. Fujitsu también tiene procesadores Sparc de 64 bits con DFP en el hardware. [7] [2]
El estándar IEEE 754-2008 define representaciones decimales en coma flotante 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 una mantisa . A diferencia del formato binario de coma flotante, 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 la mantisa es cero, el exponente puede ser cualquier valor.
Los rangos de exponentes se eligieron de modo que el rango disponible para los valores normalizados sea aproximadamente simétrico. Como esto no se puede hacer exactamente con un número par de posibles valores de exponente, se le asignó el valor adicional a Emax.
Se definen dos representaciones diferentes:
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 a 2, y los 4 bits más significativos del mantis están limitados al rango de 0 a 9. Las 30 combinaciones posibles están codificadas 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, significado con 0mmms 10mmm xxx El exponente comienza con 10, significando con 0mmm
Si los 4 bits iniciales del mantis 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, significando con 100ms 1101m xxx El exponente comienza con 01, significando con 100ms 1110m xxx El exponente comienza con 10, significando con 100m
El bit inicial (s en lo anterior) es un bit de signo, y los bits siguientes (xxx en lo anterior) codifican los bits de exponente adicionales y el resto del dígito más significativo, pero los detalles varían dependiendo de 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 (ver línea de números reales extendida )s 11111 0 NaN silencioso (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 que es posible inicializar una matriz en NaN llenándola con un único valor de byte.
Este formato utiliza un mantra binario de 0 a 10 p −1. Por ejemplo, el mantra del decimal 32 puede ser hasta 10 7 −1 = 9 999 999 = 98967F 16 = 1001 1000100101 1001111111 2 . Si bien la codificación puede representar mantras más grandes, son ilegales y el estándar requiere que las implementaciones los traten 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 los 6 bits del "campo de continuación de exponente"), y el mantisa son los 23 bits restantes, con un bit 0 inicial 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 dígito significativo principal es 0.
Si los 2 bits después del bit de signo son "11", entonces el campo de exponente de 8 bits se desplaza 2 bits hacia la derecha (después del bit de signo y de los bits "11" posteriores), y el significado representado está en los 21 bits restantes. En este caso, hay una secuencia inicial implícita (es decir, no almacenada) de 3 bits "100" en el significado verdadero:
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 implícito "100" de 3 bits para el significando.
Tenga en cuenta que los bits iniciales del campo de mantisa no codifican el dígito decimal más significativo; son simplemente parte de un número binario puro más grande. Por ejemplo, una mantisa de 8 000 000 se codifica como binario 0111 1010000100 1000000000 , con los 4 bits iniciales codificando 7; la primera mantisa 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:
Decimal64 y Decimal128 funcionan de manera análoga, pero con campos de continuación de exponente y significando más grandes. Para Decimal128, la segunda forma de codificación en realidad nunca se usa; el mayor significando válido de 10 34 −1 = 1ED09BEAD87C0378D8E63FFFFFFFF 16 se puede representar en 113 bits.
En esta versión, la mantisa 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 de la mantisa utiliza la codificación decimal densamente empaquetada (DPD).
Los dos primeros bits del exponente y el dígito inicial (3 o 4 bits) de la mantisa se combinan en los cinco bits que siguen al bit de signo. A esto le sigue un campo de continuación de exponente con desplazamiento fijo.
Finalmente, el campo de continuación del significado está formado por 2, 5 u 11 declets de 10 bits , cada uno de los cuales codifica 3 dígitos decimales. [8]
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 siguientes se interpretan como el dígito decimal inicial (0 a 7): [9]
Exponente combinado 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", entonces los dos segundos bits son los bits iniciales del exponente, y el último bit tiene como prefijo "100" para formar el dígito decimal inicial (8 o 9):
Exponente combinado 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 NaNs, respectivamente.
La regla habitual para realizar operaciones aritméticas de punto flotante es que se calcula el valor matemático exacto [10] y luego se redondea el resultado al valor representable más cercano con 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, en los ejemplos se utilizará una precisión de 7 dígitos. Los principios fundamentales son los mismos en cualquier precisión.
Un método sencillo para sumar números de punto flotante es representarlos primero con el mismo exponente. En el ejemplo siguiente, el segundo número se desplaza 3 dígitos hacia la derecha. Procedemos con el método de suma 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 otra cosa que convertir 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 del cambio)-------------------- e=5; s=1,235584654 (suma verdadera: 123558,4654)
Este es el resultado real, 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 inferiores del segundo operando (654) se pierden esencialmente. Esto 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 significancia ocurre cuando se restan las aproximaciones a dos números casi iguales. En el siguiente ejemplo, e = 5; s = 1,234571 y e = 5; s = 1,234567 son aproximaciones a 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 y la normalización)
La diferencia de punto flotante se calcula exactamente porque los números son cercanos: el lema de Sterbenz garantiza esto, incluso en caso de desbordamiento por defecto cuando se admite el desbordamiento por defecto gradual . A pesar de esto, la diferencia de los números originales es e = −1; s = 4.877000, que difiere más del 20% de la diferencia e = −1; s = 4.000000 de las aproximaciones. En casos extremos, se pueden perder todos los dígitos significativos de precisión. [11] [12] Esta cancelación ilustra el peligro de suponer que todos los dígitos de un resultado calculado son significativos. El tratamiento de las consecuencias de estos errores es un tema del análisis numérico ; consulte también Problemas de precisión.
Para multiplicar se multiplican los mantis, 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 hace de manera similar, pero es más complicada.
No existen problemas de cancelación o absorción en la multiplicación o división, aunque pueden acumularse pequeños errores a medida que se realizan operaciones repetidamente. En la práctica, la forma en que se llevan a cabo estas operaciones en la lógica digital puede ser bastante compleja.
{{cite book}}
: CS1 maint: location missing publisher (link)