Pregunta

En la carrera, me han dicho:

  

valores continuas se representaron aproximadamente en la memoria, y por lo tanto de computación con flotadores implica errores de redondeo. Estas son pequeñas discrepancias en patrones de bits; así la e==f prueba es inseguro si e y f son flotadores.

En referencia a Java.

¿Es esto cierto? He utilizado estados comparación con doubles y floats y nunca he tenido problemas de redondeo. Nunca he leído en un libro de texto algo similar. Sin duda, representa la máquina virtual para esto?

¿Fue útil?

Solución

Es verdad.

Es una limitación inherente de los valores de punto cómo flotantes están representados en la memoria en un número finito de bits.

Este programa, por ejemplo, impresiones de "falsa":

public class Main {
  public static void main(String[] args) {
    double a = 0.7;
    double b = 0.9;
    double x = a + 0.1;
    double y = b - 0.1;
    System.out.println(x == y);
  }
}

En lugar de comparación exacta con '==' por lo general a decidir en algún nivel de precisión y pregunte si los números están "lo suficientemente cerca":

System.out.println(Math.abs(x - y) < 0.0001);

Otros consejos

Esto se aplica a Java, tanto como a cualquier otro idioma con coma flotante. Es inherente en el diseño de la representación de los valores de punto flotante en hardware.

Más información sobre los valores de punto flotante:

Lo que todo informático debe saber sobre Floating Point-Aritmética

Sí, lo que representa 0,1 exactamente en base 2 es lo mismo que tratar de representar exactamente 1/3 de la base 10.

Esto es siempre cierto. Hay algunos números que no se pueden representar con precisión utilizando la representación de punto flotante. Consideremos, por ejemplo, pi. ¿Cómo te representar un número que tiene infinitas cifras, dentro de un almacenamiento finita? Por lo tanto, al comparar los números se debe comprobar si la diferencia entre ellos es más pequeño que algunos épsilon. Además, hay varias clases que existen que pueden ayudarle a lograr una mayor precisión, como BigDecimal y BigInteger.

Es correcto. Tenga en cuenta que Java no tiene nada que ver con ello, el problema es inherente a la aritmética de punto flotante en CUALQUIER idioma.

A menudo puede salirse con la suya con problemas a nivel de aula, pero no va a funcionar en el mundo real. A veces no va a funcionar en el aula.

Un incidente de hace mucho tiempo atrás en la escuela. El maestro de una clase de introducción le asigna un último problema examen que estaba resultando un doozy real para muchos de los mejores estudiantes - que no estaba funcionando y que no sabía por qué. (Vi esto como asistente de laboratorio, que no estaba en la clase.) Por último, algunos empezaron a pedir ayuda y algunos sondeo revelado el problema:. Nunca habían sido enseñado sobre la inexactitud inherente de la aritmética de punto flotante

Ahora, hay dos enfoques básicos para este problema, una fuerza bruta uno (que casualmente trabajaba en este caso, ya que hizo los mismos errores cada vez) y una más elegante uno (lo que haría diferentes errores y no trabajar. ) cualquier persona que intentó el enfoque elegante que golpear una pared de ladrillos sin tener ninguna idea de por qué. Ayudé a un montón de ellos y atrapado en un comentario explicando por qué y ponerse en contacto conmigo si tenía preguntas.

Por supuesto próximo semestre que escucho de él sobre esto y yo básicamente plantas ha todo el departamento con un simple pequeño programa:

10 X = 3000000
20 X = X + 1
30 If X < X + 1 goto 20
40 Print "X = X + 1"

A pesar de lo que cada profesor en el departamento pensó, este por terminado. La semilla de 3 millones es simplemente para que sea terminar más rápido. (Si usted no sabe básica: No hay trucos aquí, sólo agotar la precisión de los números de punto flotante.)

Sí, como otros han dicho respuestas. Quiero añadir que os recomiendo este artículo acerca de coma flotante de precisión: Visualizando flotadores

La mayoría de las CPU (y lenguajes de programación) utilizan IEEE 754 aritmética de coma flotante. Usando esta notación, hay números decimales que no tienen ninguna representación exacta en esta notación, por ejemplo, 0.1. Así que si se divide por 1 10 no obtendrá un resultado exacto. Al realizar varios cálculos en una fila, los errores resumen. Pruebe el siguiente ejemplo en Python:

>>> 0.1
0.10000000000000001
>>> 0.1 / 7 * 10 * 7 == 1
False

Eso no es realmente lo que se espera matemáticamente.

Por cierto: Un malentendido común con respecto a los números de punto flotante es, que los resultados no son precisos y no pueden ser comapared segura. Esto sólo es cierto si realmente utiliza fracciones de números. Si todo su matemática está en el dominio entero, dobles y flotadores hacen exactamente lo mismo que enteros y también puede ser comparado con seguridad. Se pueden utilizar con seguridad como contadores de bucles, por ejemplo.

Sí, Java también utiliza la aritmética punto flotante.

Por supuesto, es cierto. Piénsalo. Cualquier número debe estar representado en binario.

foto: "1000" como 0.5or medio, es decir, 2 ** -1. A continuación, "0100" es 0,25 o 1/4. Se puede ver a dónde voy.

¿Cuántos números se puede representar de esta manera? 2 ** 4. La adición de más bits duplica el espacio disponible, pero nunca es infinita. 1/3 o 1/10, para la materia 1 / n, cualquier número no múltiplo de 2 no puede ser realmente representados.

1/3 podría ser "0101" (0.3125) o "0110" (0.375). De cualquier valor si se multiplica por 3, no será 1. Por supuesto, se podría añadir reglas especiales. Puedes decir "cuando se agrega 3 veces '0101', poner el partido 1" ... este enfoque no funcionará en el largo plazo. Puede tomar un poco, pero entonces ¿qué 1/6 veces 2?

No es un problema de la representación binaria, cualquier representación finita tiene números que no se puede representar, que son infinitos, después de todo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top