(Completado) Tutorial para entender los errores de punto flotante de IEEE

Exención de responsabilidades de contenido KB retirado

Este artículo se refiere a productos para los que Microsoft ya no ofrece soporte técnico. Por tanto, el presente artículo se ofrece "tal cual" y no será actualizado.

Resumen

Matemáticas de punto flotante son un tema complejo que confunde a muchos programadores. El siguiente tutorial debería ayudarle a reconocer situaciones de programación donde es probable que se produzcan errores de punto flotante y cómo evitarlos. También debe permitir reconocer casos causadas por limitaciones de inherente matemáticas de punto flotante en contraposición a los errores del compilador real.

Más información

Sistemas de numeración binario y decimal

Normalmente, contamos cosas en base 10. La base es completamente arbitraria. La única razón que personas han utilizado tradicionalmente en base 10 es que tienen 10 dedos, que han hecho útiles herramientas de recuento.


El número 532.25 en decimal (base 10) significa lo siguiente:

   (5 * 10^2) + (3 * 10^1) + (2 * 10^0) + (2 * 10^-1) + (5 * 10^-2)
500 + 30 + 2 + 2/10 + 5/100
_________
= 532.25


En el sistema de numeración binario (base 2), cada columna representa una potencia de 2 en lugar de 10. Por ejemplo, el número 101.01 significa lo siguiente:

   (1 * 2^2) + (0 * 2^1) + (1 * 2^0) + (0 * 2^-1) + (1 * 2^-2)
4 + 0 + 1 + 0 + 1/4
_________
= 5.25 Decimal


Cómo se representan los enteros en PCs

Porque no hay ningún parte fraccionaria en un entero, su representación de equipo es mucho más sencilla de lo que es para valores de punto flotante. Los nteros normales en ordenadores personales (PC) tienen 2 bytes (16 bits) con el bit más significativo que indica el signo. Enteros largos tienen una longitud de 4 bytes. Los valores positivos son números binarios sencillo. Por ejemplo:

    1 Decimal = 1 Binary
2 Decimal = 10 Binary
22 Decimal = 10110 Binary, etc.


Sin embargo, enteros negativos se representan mediante la combinación de complemento de dos. Para obtener la representación del complemento de dos de un número negativo, tomar la representación binaria de valor de absoluto del número y voltear todos los bits y agregar 1. Por ejemplo:

   4 Decimal = 0000 0000 0000 0100
1111 1111 1111 1011 Flip the Bits
-4 = 1111 1111 1111 1100 Add 1


Tenga en cuenta que -1 Decimal = 1111 1111 1111 1111 en binario, que explica por qué Basic considera -1 como lógico true (todos los bits = 1). Esto es una consecuencia de no tener operadores distintos para las comparaciones lógicas y bit a bit. A menudo en Basic, es conveniente utilizar el fragmento de código siguiente, cuando el programa y muchas comparaciones lógicas. Esto ayuda en gran medida la legibilidad.

   CONST TRUE = -1
CONST FALSE = NOT TRUE


Tenga en cuenta que al agregar cualquier combinación de dos complementar números juntos mediante normal aritmética binaria produce el resultado correcto.

Complicaciones de punto flotante

Cada entero decimal puede representarse exactamente por un entero binario; Sin embargo, esto no es cierto para los números fraccionarios. De hecho, cada número de irrational en base 10 también será irracional en cualquier sistema con una base menor a 10.


Para los binarios, en particular, los números fraccionarios sólo pueden representarse de la forma p/q, donde q es un entero potencia de 2, que se puede expresar exactamente, con un número finito de bits.


Fracciones de decimales incluso comunes, como el 0.0001 decimal, no se puede representar exactamente en binario. (0.0001 es una fracción binaria extensible con un período de 104 bits)!


Esto explica por qué un ejemplo sencillo, como el siguiente:

   SUM = 0
FOR I% = 1 TO 10000
SUM = SUM + 0.0001
NEXT I%
PRINT SUM ' Theoretically = 1.0.


IMPRIMIR 1.000054 como salida. El pequeño error al representar 0.0001 en binario se propaga a la suma.


Por la misma razón, siempre debe tener mucho cuidado al realizar comparaciones con los números reales. En el ejemplo siguiente se muestra un error de programación común:

   item1# = 69.82#
item2# = 69.20# + 0.62#
IF item1# = item2# then print "Equality!"


Esto no IMPRIMIRÁ "Igualdad!" porque 69.82 no se puede representar exactamente en binario, que hace que el valor que resulta de la asignación a ser LIGERAMENTE distintos (en binario) que el valor que se genera a partir de la expresión. En la práctica, deberá codificar siempre estas comparaciones de tal manera que se permita la cierta tolerancia. Por ejemplo:

   IF (item1# < 69.83#) AND (item1# > 69.81#) then print "Equal"


Se IMPRIMIRÁ "Igual".

Números de formato IEEE

QuickBasic para MS-DOS, versión 3.0 fue enviado con una versión MBF (Microsoft Binary Floating Point) y una versión de IEEE (Institute of Electrical and Electronics Engineers) para equipos con un coprocesador matemático. QuickBasic para MS-DOS, versión 4.0 y posteriores sólo utiliza IEEE. Microsoft ha elegido el estándar IEEE para representar valores de punto flotante en las versiones actuales de Basic para las siguientes tres razones principales:

  1. Para permitir que Basic utilizar los coprocesadores matemáticos Intel, que utilizan formato IEEE. Los coprocesadores 80 x 87 serie Intel no pueden trabajar con números de formato binario de Microsoft.
  2. Realizar interlanguage llamada entre Basic, C, Pascal, FORTRAN y MASM mucho más fácil. De lo contrario, las rutinas de conversión tendría que se utilizará para enviar los valores numéricos de un idioma a otro.
  3. Para lograr la coherencia. IEEE es el estándar aceptado para los compiladores de C y FORTRAN.
La siguiente es una comparación rápida de IEEE y MBF representaciones para un número de precisión doble:

               Sign Bits   Exponent Bits   Mantissa Bits
--------- ------------- -------------
IEEE 1 11 52 + 1 (Implied)
MBF 1 8 56


Para obtener más información sobre las diferencias entre una representación de punto flotante IEEE y MBF, consulta en Microsoft Knowledge Base, las palabras siguientes:

   IEEE and floating and point and appnote


Tenga en cuenta que IEEE tiene más bits dedicados al exponente, lo que permite representar una gama más amplia de valores. MBF tiene más bits de mantisa, que le permite ser más precisos dentro de su alcance más estrecho.

Conceptos generales de punto flotante

Es muy importante tener en cuenta que cualquier sistema de punto flotante binario puede representar sólo un número finito de valores de punto flotante en forma exacta. Todos los demás valores deben calcularse el valor representable más cercano. El estándar IEEE especifica el método de redondeo de valores hasta el valor representable "más próximo". QuickBasic para MS-DOS es compatible con el estándar y redondea según las normas IEEE.


Además, tenga en cuenta que los números que se pueden representar en IEEE se reparten entre una gama muy amplia. Se puede considerar en una línea de número. Hay una alta densidad de números representables cerca 1.0 y -1.0 pero menos que ir hacia 0 o infinito.


El objetivo de la norma IEEE, que está diseñado para cálculos de ingeniería, es maximizar la precisión (para obtener lo más cerca posible de los datos reales de número). Precisión hace referencia al número de dígitos que puede representar. El estándar IEEE intenta equilibrar el número de bits dedicados al exponente con el número de bits utilizados para la parte fraccionaria del número, para mantener la exactitud y la precisión dentro de límites aceptables.

Detalles de IEEE

Números de punto flotante se representan en el formato siguiente, donde [exponente] es el exponente binario:

   X =  Fraction * 2^(exponent - bias)


[Fracción] es la parte fraccionaria normalizada del número, normalizado porque el exponente se ajusta para que el bit inicial sea siempre un 1. De este modo, no tiene que almacenarse y obtiene más de un bit de precisión. Esto es por qué hay un bit implícito. Se puede considerar esto como notación científica, donde se manipula el exponente para tener un dígito a la izquierda del separador decimal, excepto en binario, siempre puede manipular al exponente para que el primer bit sea un 1, ya que hay sólo números 1 y 0.


[diferencia] es el valor de diferencia para evitar tener que almacenar a los exponentes negativos.


El sesgo para los números de precisión simple es 127 y 1023 (decimal) para los números de doble precisión.


Los valores igual a todo 0 y todo 1 (binario) se reservan para representar los casos especiales. Hay otros casos especiales, que indican las diversas condiciones de error.

Ejemplos de precisión simple

2 = 1 * 2 ^ 1 = 0100 0000 0000 0000... 0000 0000 = 4000 0000 hex
Nota el bit de signo es cero y el exponente almacenado es 128, o 100 0000 0 en binario, que equivale a 127 más 1. La mantisa almacenada es (1.) 000 0000... 0000 0000, que tiene un implícito líder 1 y un punto binario, la mantisa real es 1.

-2 = -1 * 2 ^ 1 = 1100 0000 0000 0000... 0000 0000 = C000 hex de 0000
Igual que + 2, excepto en que está establecido el bit de signo. Esto es cierto para todos los números IEEE de punto flotante de formato.

4 = 1 * 2 ^ 2 = 0100 0000 1000 0000... 0000 0000 = 4080 0000 hex
La misma mantisa exponente aumenta en uno (valor sesgado es 129, o 100 0000 1 en binario.

6 = 1,5 * 2 ^ 2 = 0100 0000 1100 0000... 0000 0000 = 40C 0 0000 hex
Mismo exponente, mantisa es mayor a la mitad: es (1,) 100 0000... 0000 0000, que, como es una fracción binaria, es 1 1/2 (los valores de los dígitos fraccionarios son 1/2, 1/4, 1/8, etc..).

1 = 1 * 2 ^ 0 = 0011 1111 1000 0000... 0000 0000 = 3F80 0000 hex
Mismo exponente que otras potencias de 2, mantisa es uno menos que 2 a 127 o 011 1111 1 en binario.

.75 = 1,5 * 2 ^ -1 = 0011 1111 0100 0000... 0000 0000 = 3F40 0000 hex
El exponente sesgado es 126, 011 1111 0 en binario y la mantisa es (1,) 100 0000... 0000 0000, que es 1-1/2.

2,5 = 1,25 * 2 ^ 1 = 0100 0000 0010 0000... 0000 0000 = 4020 0000 hex
Exactamente igual que 2, excepto que el bit que representa 1/4 está establecido en la mantisa.

1.6 = 0,1 * 2 ^ -4 = 0011 1101 1100 1100... 1100 1101 = 3DCC CCCD hex
1/10 es una fracción que se repite en binario. La mantisa es una pequeña parte de 1,6, y el exponente sesgado indica que 1,6 debe dividirse por 16 (es 011 1101 1 en binario, que equivale a 123 en decimal). El exponente real es 123-127 = - 4, lo que significa que el factor por el que se debe multiplicar es 2 ** -4 = 1/16. Tenga en cuenta que la mantisa almacenada se redondea en el último bit. Se trata de un intento para representar el número no se puede representar de forma más precisa posible. (La razón por la que 1/10 y 1/100 son representables no exactamente en binario es similar a la forma en la que 1/3 es representable no exactamente en decimal.)

0 = 1.0 * 2 ^ -128 = todo ceros: un caso especial.

Otros errores comunes de punto flotante

Los siguientes son los errores comunes de punto flotante:

  1. Error de redondeo


    Este error se produce cuando todos los bits en un número binario no se puede utilizar en un cálculo.


    Ejemplo: Agregar 0.0001 a 0.9900 (precisión simple)


    0.0001 decimal se representarán como:
    (1) 10100011011011100010111 * 2^(-14+Bias) (13 líderes 0s en binario!)
    0.9900 se representarán como:
    (1.)11111010111000010100011 * 2^(-1+Bias)
    Ahora para agregar realmente estos números, deben alinear los puntos decimales (binarios). Para ello deben ser desnormalizados. Aquí está la suma resultante:
           .000000000000011010001101 * 2^0  <- Only 11 of 23 Bits retained
    +.111111010111000010100011 * 2^0
    ________________________________
    .111111010111011100110000 * 2^0


    Esto se denomina un error de redondeo ya que algunos equipos redondean al cambiar de adición. Otros simplemente truncan. Los errores de redondeo son importantes para tener en cuenta siempre que se va a agregar o multiplicar dos valores muy diferentes.
  2. Resta dos casi igualan valores
           .1235
    -.1234
    _____
    .0001


    Esto se normalizará. Tenga en cuenta que, aunque los números originales tenían cuatro dígitos significativos, el resultado tiene un solo dígito significativo.
  3. Desbordamiento y subdesbordamiento


    Esto ocurre cuando el resultado es demasiado grande o demasiado pequeño para ser representado por el tipo de datos.
  4. Error de cuantificación


    Esto ocurre con los números que no se pueden representar en forma exacta en el estándar de punto flotante.
  5. División de un número muy pequeño


    Esto puede desencadenar un error "división por cero" o puede producir resultados incorrectos, como en el ejemplo siguiente:
          A = 112000000
    B = 100000
    C = 0.0009
    X = A - B / C


    En QuickBasic para MS-DOS, X ahora tiene el valor 888887, en lugar de la respuesta correcta, 900000.
  6. Error de salida


    Este tipo de error se produce cuando las funciones de salida modifican los valores que están trabajando con.
Propiedades

Id. de artículo: 42980 - Última revisión: 17 ene. 2017 - Revisión: 1

Comentarios