c# unity3d floating-accuracy

c# - ¿Por qué float.Epsilon y no cero?



unity3d floating-accuracy (2)

En realidad, usar float.Epsilon puede no hacer ninguna diferencia significativa aquí. float.Epsilon es el float más pequeño posible mayor que cero (aproximadamente 1.401298E-45 ), lo que no significa que sea la menor diferencia entre dos float arbitrarios. Dado que la matemática de punto flotante es imprecisa, la diferencia entre dos números aparentemente iguales puede ser mucho mayor que float.Epsilon . Por ejemplo:

float f1 = 1.0f / 3.0f; float f = 1.0f; (f1 * 3).Dump(); // 1 (f1 * 3 - f).Dump(); // 2.980232E-08

Cuando se comparan flotadores, una mejor práctica es elegir un valor razonable para determinar si dos flotadores están "lo suficientemente cerca" para ser iguales. Esa es una definición contextual, por ejemplo, para distancia, ¿es 1 mm "lo suficientemente cerca"? Tal vez al construir una caseta de perro, pero no una placa de circuito. No vas a seguir cortando un trozo de madera hasta que su longitud esté a 1.401298E-45 metros del objetivo. Vas a elegir una diferencia que sea "lo suficientemente cercana" para llamarlos iguales.

Para el movimiento de sprites (que supongo que es lo que se está haciendo en la muestra), tal vez un "épsilon" más razonable sea la distancia más pequeña que se pueda representar en un monitor de alta resolución (o al menos eso lo notará el humano ojo).

Todo esto para decir que sqrRemainingDistance > 0 puede ser igual de razonable aquí, ya que no hay otro número entre 0 y float.Epsilon que el número podría ser, pero una mejor opción puede ser un número mucho más grande que Epsilon para determinar cuándo parar el bucle . El programa puede estar en bucle mucho más de lo necesario para obtener un resultado "razonable".

De hecho, está documentado en MSDN :

Si crea un algoritmo personalizado que determina si dos números de punto flotante pueden considerarse iguales, debe usar un valor que sea mayor que la constante de Epsilon para establecer el margen de diferencia absoluto aceptable para que los dos valores se consideren iguales. (Normalmente, ese margen de diferencia es muchas veces mayor que el de Epsilon).

En el siguiente código, ¿por qué hay una comparación con float.Epsilon y no 0?

// Coroutine to move elements protected IEnumerator SmoothMovement (Vector3 end) { // Distance computation float sqrRemainingDistance = (transform.position - end).sqrMagnitude; while(sqrRemainingDistance > float.Epsilon) { Vector3 newPostion = Vector3.MoveTowards( rb2D.position, end, inverseMoveTime * Time.deltaTime ); rb2D.MovePosition (newPostion); sqrRemainingDistance = (transform.position - end).sqrMagnitude; yield return null; } }


Porque la matemática de coma flotante no es precisa . El artículo que vinculé es largo y detallado, así que déjame explicarte con un ejemplo simple:

43.65 + 61.11 = 104.75999999999999

La razón detrás es cómo se guardan realmente los números de punto flotante. Si no desea sumergirse en esto, solo tenga en cuenta las limitaciones generales de la aritmética de punto flotante y no espere que sean exactamente lo que deberían ser de acuerdo con las matemáticas, incluido, en este caso, 0.