¿Cómo convierto un número real como 0.72 a un binario? ¿Por qué necesito seguir multiplicando el número por 2?
Para convertir un número de coma flotante, [math] x, [/ math] que está entre 0 y 1, a binario, el procedimiento construye una cadena de resultados de la siguiente manera: Primero, inicialice la cadena de resultados a “0”. Luego, siempre que [math] x [/ math] sea distinto de cero, realice un ciclo en el que verifique si [math] 2x \ ge 1, [/ math] y, si es así, agregue “1” al resultado, doble x, y resta 1. Por otro lado, si [matemática] 2x <1, [/ matemática] entonces agregue “0” al resultado, y doble x. Cada vez que dobla x, esencialmente cambia la representación interna de coma flotante de [math] x [/ math] un bit hacia la izquierda, con el bit más a la izquierda moviéndose al lugar “unos”. (El programa llama al número "número", pero lo he estado llamando "x" por simplicidad).
El programa que vinculó en su fuente de preguntas es defectuoso de varias maneras. El primer error que noté es que el programa omite la duplicación de [math] x [/ math] en el caso donde [math] 2x <1, [/ math] por lo que agregará un montón de ceros al resultado. Otro problema con el problema vinculado es que produce un ajuste sibilante cuando la cadena de resultados es más larga que 32 bits. La mayoría de las computadoras almacenan los llamados números de coma flotante de "doble precisión" que usan 64 bits, típicamente 53 bits para el "significado" con signo y 11 bits para el exponente con signo. [1] Entonces, al duplicar y restar 1 cuando sea necesario, se quedará sin dígitos almacenados después de hasta 53 iteraciones del bucle. Por lo tanto, el programa debe abstenerse de lanzar un ataque sibilante hasta que el tamaño del resultado esté más allá de la precisión de los números de coma flotante en su computadora. El último problema que noté con el programa es que produce un resultado incorrecto si la entrada es exactamente 1. La prueba inicial que verifica que el número es menor o igual a 1 debe cambiarse para garantizar que el número de entrada sea menor que 1. Además, la comprobación de errores inicial permite que el número de entrada sea exactamente 0. El resultado que se devuelve es "0", que es técnicamente correcto, pero no es habitual tener un punto decimal sin ningún dígito que lo siga. Un programa estéticamente más agradable devolvería "0" en lugar de "0".
También vale la pena señalar que el número real 0.72, o 18/25, no se puede almacenar exactamente en un número de punto flotante binario de 64 bits. Esto se debe a que 18/25 es un número binario repetitivo, que resulta ser [matemático] 0. \ overline {10111000010100011110}. [/ Matemático] Si realiza la lógica de su programa manualmente, verá que hay un bucle. Después de 20 iteraciones, obtienes el valor de 0,72 en x nuevamente. Pero en el mundo real, dado que el número no se había almacenado exactamente en el número de coma flotante original, obtienes 0.719999999972 en x después de 20 iteraciones. De hecho, en cada iteración del programa, todo el número de coma flotante se desplaza un bit hacia la izquierda y se agrega un cero al lado derecho. Entonces, después de 54 iteraciones en el mundo real, el programa necesariamente terminará.
- ¿Cuál es la diferencia entre letras y números? ¿Cuál es la diferencia entre literatura y matemáticas?
- ¿Cuál es la realidad del número 8,000,980,009?
- ¿Cuál es la solución para {2 ^ 50 + 3 ^ 50 + 5 ^ 50} ^ 50 mod 50?
- ¿Qué es 975898 redondeado a 5 cifras significativas?
- ¿Cuál es mayor, x ^ (infinito) o (infinito) ^ x?
Para darle una idea de por qué 18/25 es una fracción repetitiva en binario, dibujaré un paralelo con 1/7 en decimal. Así como el denominador de 1/7, 7, no es un factor de ninguna potencia de la base, 10, el denominador de 18/25, 25, no es un factor de ninguna potencia de la base, 2. Pero en la base 10 , resulta que 1/7 es igual a 142857/999999. Entonces 1/7 también es igual a 1428571428157/999999999999, etc. De manera similar, en la base 2, 18/25 es igual a 754974 / (2 ^ 20–1), que puede no parecer muy interesante, pero en binario, esto es 10111000010100011110 / 11111111111111111111. Entonces, ves, 18/25 es un binario repetitivo, al igual que 1/7 es un decimal repetitivo.
Dicho todo esto, su pregunta es sobre cómo debería funcionar el programa, por lo que responderé su pregunta con ese objetivo en mente. Si el programa funcionara correctamente, dada la representación necesariamente inexacta de 0.72 en binario, entonces funcionaría así, comenzando con 0.72.
[matemáticas] x [/ matemáticas] es 0.72. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemáticas] x [/ matemáticas] es 0.44. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemática] x [/ matemática] es 0.88. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemáticas] x [/ matemáticas] es 0.76. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.52. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemáticas] x [/ matemáticas] es 0.04. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0.08. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemática] x [/ matemática] es 0.16. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0,32. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0.64. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemáticas] x [/ matemáticas] es 0.28. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemática] x [/ matemática] es 0.56. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.12. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0.24. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0.48. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemática] x [/ matemática] es 0.959999999999. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemáticas] x [/ matemáticas] es 0.919999999998. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.839999999997. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.679999999993. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.359999999986. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0.719999999972. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.439999999944. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemática] x [/ matemática] es 0.879999999888. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.759999999776. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.519999999553. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.039999999106. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0.079999998212. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemática] x [/ matemática] es 0.159999996424. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0.319999992847. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0.639999985695. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemáticas] x [/ matemáticas] es 0.27999997139. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemática] x [/ matemática] es 0.55999994278. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.119999885559. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0.239999771118. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemática] x [/ matemática] es 0.479999542236. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemática] x [/ matemática] es 0.959999084473. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemáticas] x [/ matemáticas] es 0.919998168945. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemáticas] x [/ matemáticas] es 0.839996337891. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.679992675781. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.359985351563. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0.719970703125. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.43994140625. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0.8798828125. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.759765625. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.51953125. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.0390625. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemática] x [/ matemática] es 0.078125. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemática] x [/ matemática] es 0.15625. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0.3125. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemática] x [/ matemática] es 0.625. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemática] x [/ matemática] es 0.25. [matemática] 2x <1, [/ matemática] por lo tanto agregue "0" a la cadena de resultados y establezca [matemática] x = 2x. [/ matemática]
[matemáticas] x [/ matemáticas] es 0.5. [math] 2x \ ge 1, [/ math] entonces agregue “1” a la cadena de resultados y establezca [math] x = 2x-1. [/ math]
[matemáticas] x [/ matemáticas] es 0. El resultado final es 0.1011100001010001111010111000010100011110101110000101.
Ediciones y Agradecimientos
Gracias a Peter Pangritz por llamar la atención sobre la diferencia entre la representación de 0.72 como un número binario repetitivo y la realización por computadora de ese número binario. Actualicé la respuesta para explicar cómo funciona esto.
Notas al pie
[1] Aritmética de punto flotante – Wikipedia