I have just noticed that the following code returns true:
Mathf.Approximately(0.0f, float.Epsilon); // true
I have read the Mathf.Approximately Documentation and it states that:
Approximately() compares two floats and returns true if they are within a small value (Epsilon) of each other.
And Mathf.Epsilon Documentation states that:
- anyValue + Epsilon = anyValue
- anyValue - Epsilon = anyValue
- 0 + Epsilon = Epsilon
- 0 - Epsilon = -Epsilon
As a result, I ran the following code, expecting it to be false
, but it also returns true
.
Mathf.Approximately(0.0f, 2.0f * float.Epsilon); // true
By the way:
Mathf.Approximately(0.0f, 2.0f * float.Epsilon); // true
Mathf.Approximately(0.0f, 3.0f * float.Epsilon); // true
Mathf.Approximately(0.0f, 4.0f * float.Epsilon); // true
Mathf.Approximately(0.0f, 5.0f * float.Epsilon); // true
Mathf.Approximately(0.0f, 6.0f * float.Epsilon); // true
Mathf.Approximately(0.0f, 7.0f * float.Epsilon); // true
Mathf.Approximately(0.0f, 8.0f * float.Epsilon); // false
Mathf.Approximately(0.0f, 9.0f * float.Epsilon); // false
Q: Based on that evidence, can I safely say that Mathf.Approximately
is not correctly implemented according to its documentation*?
(* and as a result, I should move to different solutions, such as the one in Floating point comparison functions for C#)
Description. A tiny floating point value (Read Only). The smallest value that a float can have different from zero. With the following rules: anyValue + Epsilon = anyValue.
The value of the Epsilon property is not equivalent to machine epsilon, which represents the upper bound of the relative error due to rounding in floating-point arithmetic. The value of this constant is 1.4e-45.
If we do have to compare two floating-point numbers then rather than using “==” operator we will find the absolute difference between the numbers (which if were correctly represented, the difference would have been 0) and compare it with a very small number 1e-9 (i.e 10^-9, this number is very small) and if the ...
Here is the decompiled code of Unity's public static bool Mathf.Approximately(float a, float b);
You can see the * 8.0f
at the end ^^, so a truely badly documented method indeed.
/// <summary>
/// <para>Compares two floating point values if they are similar.</para>
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
public static bool Approximately(float a, float b)
{
return (double) Mathf.Abs(b - a) < (double) Mathf.Max(1E-06f * Mathf.Max(Mathf.Abs(a),
Mathf.Abs(b)), Mathf.Epsilon * 8.0f);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With