¿Por qué 0.8 * 3 devuelve 2.4000000000000004 en lugar de 2.4?

Esto se debe a 2 factores: primero la conversión entre bases numéricas, y segundo la forma en que el número binario se almacena en la computadora (en todas partes de la computadora desde el disco, a través de la RAM y en los registros de la CPU). La combinación de estos factores es lo que produce esos números de “casi pero sin cigarro” que encuentras.

La conversión entre bases significa que cualquier dígito tiene un alcance mayor o menor dependiendo del factor base. Por ejemplo, en base diez (decimal, como está acostumbrado a escribir en estos días) cualquier dígito tiene un alcance de 10 valores posibles. Pero en las computadoras todo funciona en binario (base 2, es decir, solo 2 valores posibles por dígito … de los cuales 0 o 1).

Ahora digamos que convierte 0.6 en decimal a binario … esto produciría una cadena de dígitos sin fin:
0.1001100110011001100110 … continuó hasta el infinito

Si ese fuera el único problema, entonces tendría algo como números de precisión arbitrarios en las computadoras. En ese caso, un solo valor consumiría toda su RAM y su computadora se bloquearía, no importa, una simple multiplicación tardaría días en completarse. Entonces, en lugar de quedarse con números arbitrarios (es decir, “infinitos” hasta la capacidad de RAM), las computadoras usan números “finitos” dados solo un conjunto fijo de dígitos. La forma más común en que una computadora almacena estas fracciones es usando números de coma flotante de la siguiente manera (coma flotante de 32 bits IEEE 754):
[un dígito para el signo +/-] [8 dígitos para el exponente] [23 dígitos para la mantisa o valor]

Entonces, en este caso, 0.6 se almacena como:
[0] [01111110] [00110011001100110011010]

Por lo tanto, ese último conjunto de dígitos simplemente se tira, llamado truncado. Ahora, ¿qué sucede cuando vuelves a convertir eso a decimal para que pueda mostrarse para tu placer de lectura? Si lo muestra con la máxima precisión decimal:
0.6000000238418579

Vaya, eso no era lo que querías, ¿verdad?

Lamentablemente es una compensación. O usa este número truncado incorporado para algo “casi” exacto, o tiene computadoras que funcionan extremadamente lentamente (si es que lo hacen) porque los números no encajan bien en binario.

Puede obtener “más” exacto aumentando el número permitido de dígitos, por ejemplo, utilizando un flotante de 64 bits (a veces llamado doble). Pero nunca puedes obtener la perfección para todos los valores posibles. Y tampoco ayuda ir con otras bases, por ejemplo, incluso el decimal tiene sus límites: ¿qué sucede con 1.0 / 3? Se vuelve:
0.333333 … repetido hasta el infinito

Pero en ternario (base 3) 1/3 se expresa exactamente como 0.1. Y 2/3 = 0.2

Entonces, cuando un número no es un factor de la base (y viceversa), tiende a encontrar estos números irracionales en esa base. Por lo tanto, no importa qué base elija, siempre tendrá este problema.

Una forma alternativa de almacenar estos números es como pares en forma de x / y. En tal caso, “puede” almacenar 1/3 como [1] [3] o en binario [0001] [0011]. Pero aún así, esto debe calcularse cada vez que usa ese número, es decir, toma más tiempo, por lo tanto, la computadora funciona más lentamente. También se han utilizado otros medios, por ejemplo, BCD http://en.wikipedia.org/wiki/Bin…

Pero todos tienen límites o incluso problemas de rendimiento extremos, como la precisión arbitraria. Por lo tanto, trate de aprender a vivir con ellos, por ejemplo, nunca espere que un punto flotante sea exacto y, en su lugar, verifique que esté dentro de un rango esperado.

Edición previa a la publicación: Oh, la gente ya respondió. Tonto de mí. Aún así, este fue un ejercicio útil para mí, y odio que se desperdicie.
——————————————–
Error de punto flotante.

Punto flotante

La aritmética de punto flotante no es algo que haya estudiado con mucha profundidad, por lo que en lugar de intentar en vano explicarlo mientras intento comprenderlo por mí mismo, presentaré algo entre un ejemplo trabajado y una analogía.

0.7 es siete una décima (0.1 * 7) en base-10, pero ¿cómo se representa en base-2, binario? En lugar de décimos, centésimos, milésimos, etc., debe trabajar con mitades, cuartos, octavos, etc., y en binario solo puede usar uno de cada uno. Entonces, ¿cuáles necesitas?

Bueno, la mitad = 0.5, entonces necesitas eso. Anunciar un cuarto es +0.25, entonces eso es demasiado. Un octavo es +0.125, por lo que estamos hasta 0.625. Sumar 1/16 nos lleva hasta 0.6875. ¡Genial, ya casi llegamos! Ahora agreguemos 1/32 … oh, eso es demasiado, ahora estamos en 0.71875. Por lo tanto, podemos intentar agregar 1/64, pero eso todavía nos pone un poco por encima. Agregar 1/128 a 0.6875 finalmente nos lleva por debajo de nuestro objetivo (0.6953125), por lo que en binario lo que tenemos ahora se parece a 0.1011001, pero aún no estamos allí. En este punto, comienza a ver el problema: hay muchos números fraccionarios que no se pueden representar exactamente en binario.

Este es el punto en el que comienza a hablar sobre precisión y cuántos bits se están utilizando. En nuestro ejemplo anterior, agreguemos también 1/256 para completar la representación en un byte completo u 8 bits (0.69921875 o 0.10110011, si tenía curiosidad). Los formatos estandarizados de coma flotante parecen reducirse a 16 bits, lo que se denomina precisión media, por lo que quizás podríamos llamar lo que tenemos “precisión de cuarto”.

Una calculadora suficientemente avanzada tendrá una precisión lo suficientemente alta como para no toparse con el problema que ha encontrado con sus cálculos; evidentemente, cualquier dispositivo que esté utilizando no tiene la precisión adecuada para realizar este cálculo según nuestros patéticos estándares humanos carnosos.

La respuesta es: 0.8 es un flotador .

Para ser almacenado en su computadora, debe convertirse a un número de precisión limitado que tiene dos partes: un significado y luego una base para la potencia de un exponente . Se puede escribir:

[matemáticas] significando * base ^ {exponente} [/ matemáticas]

El significado es una representación del número sin el punto flotante. El exponente , que es un número entero negativo, indica dónde colocar el punto flotante.

Como un flotador es una representación aproximada de un número, la aplicación de operaciones matemáticas a dos flotadores da un resultado aproximado .

Entonces, cuando escribe 0.8, su programa probablemente esté escribiendo algo similar a [math] 80000000000000001 * 10 ^ {- 17} [/ math].

Para ir un paso más allá, intente convertir 0.8 a binario y luego escríbalo en la forma: [math] significand * 2 ^ {exponent} [/ math].

Debe tener en cuenta este comportamiento cuando se trata de flotadores.

¡Espero que esto ayude!


  • Para obtener más información sobre flotadores, lea el siguiente artículo de wikipedia Punto flotante .
  • Para convertir un número decimal en base 10 a binario: ¿Cómo convertir una fracción a binario?

Esto se debe a la representación de coma flotante y al error de redondeo debido a eso.

Para saber más sobre eso, lea este artículo / artículo de David Goldberg.

Lo que todo informático debería saber sobre la aritmética de coma flotante.
( http://citeseerx.ist.psu.edu/vie …)

Es matemática de coma flotante. Error de redondeo.

http://stackoverflow.com/questio

Es porque los números en las computadoras se almacenan en binario y no en decimal. 0.8 es en realidad 4/5 y 5 no es una potencia de dos. Por lo tanto, siempre habrá un error de redondeo. Lo mismo también es cierto para 0.6, que es 3/5.

Apuesto a que funciona bien para 0.5, 0.25 y 0.625.

Oracle tenía un artículo sobre esto. Esta es una característica de los números de coma flotante: precisión de coma flotante.

http://docs.oracle.com/cd/E19957

Si yo fuera tú, me conseguiría una calculadora científica decente. Parece que estás usando un pedazo de basura que no es bueno para mucho además de las operaciones aritméticas básicas con enteros.