Coma flotante

Escribe un número decimal. Los pasos que aparecen debajo detallan la conversión tal y como la harías a mano. La línea superior representa lo que el ordenador acaba almacenando.

Cargando simulación interactiva...
Lección

La teoría — Coma flotante291 palabras

Un número en coma flotante es un número entero multiplicado por una potencia de dos: (−1)s × 1.f × 2E−1023. El formato decide cuántos bits corresponden a E y cuántos a f. Esta única división determina tanto el alcance del formato como su precisión para distinguir entre dos números.

Qué significa cada símbolo

s
el bit de signo, 0 para positivo y 1 para negativo. Va por separado en lugar de estar integrado en el número, y por eso el formato tiene un +0 y un −0.
E
el campo del exponente, almacenado con 1023 sumado para poder ser negativo sin necesitar un signo propio. Define en qué rango te encuentras, y el rango es lo que determina la distancia entre dos números vecinos.
f
la fracción: 52 bits que siguen a un 1 inicial que nunca se guarda, puesto que un número normalizado siempre empieza por uno. Esos 52 bits contienen toda la precisión, y el exponente no aporta ninguna.
Supone
Que el número es finito y normal. Por debajo de 2−1022 se descarta el 1 inicial y el formato continúa funcionando a costa de perder precisión, por lo que el valor positivo más pequeño de doble precisión es 4,94 × 10−324 y aporta un solo bit de mantisa.
Falla cuando
En dos partes, ambas en código real. Comparar dos valores calculados con = falla siempre que se llegue a ellos por vías distintas, ya que cada método aplica el redondeo a su manera. Además, una suma larga depende del orden en el que se ejecuta. Suma una lista hacia adelante y luego hacia atrás; verás que los totales difieren. Si añades primero los términos más pequeños, la pérdida es mínima.

Ocho de los mil 🖖

De los números entre 0,001 y 1,000, exactamente ocho se almacenan sin el menor error: 0,125; 0,25; 0,375; 0,5; 0,625; 0,75; 0,875 y 1. Una fracción binaria es la suma de medios, cuartos, octavos y así sucesivamente. Un denominador de 1000 conlleva un factor de 125 que ninguna potencia de dos conseguirá anular. Escribe 0,375 y la herramienta lo marcará como exacto. Escribe 0,376 y ya no lo hará.

0,1 + 0,2 cae exactamente en la mitad 🖖

Los dos valores almacenados suman 0,3000000000000000166533453693773481063544750213623046875, que es el punto medio exacto entre los dos números de doble precisión a cada lado de 0,3. La suma en sí es impecable. Es necesario deshacer el empate de alguna forma, y la regla indica que se debe tomar al vecino cuyo último bit es par. El número por debajo de 0,3 termina su fracción con un bit impar y el que está por encima con uno par, de modo que la suma se redondea hacia arriba. De ahí sale la cola en 0,30000000000000004.

Menos bits, respuesta correcta 🖖

Pulsa binary32 con los mismos dos números. 0,1 + 0,2 da como resultado 0,300000011920928955078125, que es exactamente cómo se almacena 0,3 en ese formato. El famoso fallo requiere que la suma caiga en un empate, y en 24 bits se queda a un cuarto de salto de lograrlo, por lo que se redondea de vuelta al número que esperabas. La mitad de precisión, y la respuesta que querías.

El salto se duplica en cada potencia de dos 🖖

En cualquier punto entre 0,0625 y 0,125, la distancia de un número representable al siguiente es de 1,39 × 10⁻¹⁷, y no varía en absoluto dentro de ese intervalo. Pasa al siguiente intervalo superior y se duplicará. La escalera de la gráfica es exactamente eso, un escalón por cada potencia de dos, razón por la cual un mismo formato puede almacenar 10⁻³⁰⁰ y 10³⁰⁰ pero no puede retener 9007199254740993.

Problema resuelto al detalle

  1. Un sistema de pagos almacena importes en libras usando binary64. Demuestra que tanto 0,10 £ como 0,20 £ se guardan con un valor ligeramente alto, que su suma no da 0,30 £ y explica cómo lo soluciona un ingeniero de pagos.

    1. 0,1 en base dos es 0,0001 seguido de 1001 que se repite infinitamente. Una décima necesita un cinco en su denominador, pero una fracción binaria solo tiene doses, por lo que el desarrollo nunca se cierra.

    2. Se conservan 53 dígitos binarios y los demás se eliminan por redondeo. En este caso se redondean hacia arriba, por lo que el valor almacenado supera a 0,1 en 5,55 × 10⁻¹⁸. El paso de redondeo en la página ilustra esta dirección con una flecha.

    3. 0,2 tiene esos mismos 53 dígitos con el exponente incrementado en uno, por lo que su error es exactamente el doble: 1,11 × 10⁻¹⁷. Introduce 0,2 en la casilla y compara las dos tarjetas de error.

    4. Al sumarlos, los dos valores almacenados caen exactamente en el punto medio entre los dos doubles situados a cada lado de 0,3. En caso de empate, se elige al vecino que termina en un bit par, que es el número superior.

    5. Así que lo que se obtiene es 0,3000000000000000444089209850062616169452667236328125, y cualquier cálculo posterior arrastrará este valor.

    6. Ahora teclea 10 y 20 en lugar de 0,1 y 0,2. Ambos son números enteros muy inferiores a 2⁵³, los dos se representan con exactitud, y 10 + 20 da 30 sin perder nada en el proceso.

    Respuesta

    Almacena el dinero como un número entero de la unidad más pequeña, peniques en lugar de libras, y la aritmética será exacta porque cada número entero hasta 2⁵³ es exacto. El único redondeo que queda es el que escribes tú mismo, en el momento que eliges, ahí donde puedes verlo claramente. La herramienta te muestra ambas partes en diez segundos: teclea 0,1 y la tarjeta de error no es cero, teclea 10 y sí lo es.

Problemas de ejemplo

  • 0,1 - El 0,1 se almacena como 0,1000000000000000055511151231257827021181583404541015625, y el 0,2 se excede en el doble. Su suma cae exactamente en la mitad entre los dos números a ambos lados de 0,3, por lo que la regla de desempate decide hacia dónde va, y va hacia arriba.
  • 0,375 - La serie en base dos se detiene a los tres dígitos en lugar de prolongarse hasta el infinito, y la herramienta clasifica el valor como exacto. 0,375 equivale a 3/8, y las fracciones binarias están formadas justamente por octavos. Cambia el último dígito a 0,376 y la expansión no terminará jamás.
  • 0,1 en 32 bits - El mismo 0,1 en 24 bits de significando en lugar de 53: se guarda como 0,100000001490116119384765625 y la herramienta indica 7,22 dígitos decimales. Suma 0,2 aquí y el resultado es 0,300000011920928955078125, que es exactamente como se almacena el 0,3 en este formato.
  • 2⁵³ + 1 - Por encima de 2⁵³ el salto llega a 2, por lo que falta uno de cada dos números enteros. El 9007199254740993 se sitúa exactamente entre dos de ellos y el desempate lo empuja hacia abajo hasta 9007199254740992, un error de −1. Sumarle 1 no cambia nada, por el mismo motivo.
  • 10¹⁶ + 1 - El 10¹⁶ se almacena con exactitud y el 1 también, por lo que 10¹⁶ + 1 devuelve 10¹⁶. Aquí el salto es de 2, de forma que 10000000000000001 supone un empate entre dos vecinos, y la regla del último bit par que empujó hacia arriba el 0,1 + 0,2 empuja este de vuelta hacia abajo.