Search Unity

Wrong Epsilon value

Discussion in 'Editor & General Support' started by Fixe, Mar 27, 2014.

  1. Fixe

    Fixe

    Joined:
    Sep 18, 2012
    Posts:
    29
    Actually Unity states that Epsilon is the smallest positive float (while it is common conception that Epsilone is something else):
    http://docs.unity3d.com/Documentation/ScriptReference/Mathf.Epsilon.html

    Needs some work!

    1) Epsilon in licterature usually is the smallest number that can be added to 1 (for 32-bit IEEE floating point numbers it is 1/2^23), any number smaller than Epsilon added to 1 results in 1.

    (a+b == a) <==> (b < Epsilon * a)

    2) Even if Unity intention is to use Epsilon as the smallest positive float the following function

    Code (csharp):
    1.  bool isEqual(float a, float b) {
    2.         if (a >= b - Mathf.Epsilon  a <= b + Mathf.Epsilon)
    3.             return true;
    4.         else
    5.             return false;
    6.     }
    makes absolutely no sense, it will be just a waste of clock cycles since it will always returns:

    Code (csharp):
    1.  bool isEqual(float a, float b) {
    2.         return a==b;
    3.     }
    a proper solution would be

    Code (csharp):
    1.  bool isEqual(float a, float b, float relativeError) {
    2.         if (a >= b*(1-relativeError)  a <= b*(1+relativeError))
    3.             return true;
    4.         else
    5.             return false;
    6.     }


    here, someone may wants to use as relativeError the true epsilon (1/2^23) but in general, the admitted error is really application dependent,

    3)
    More significative statement:

    "If result from an algebric operation is some number very similiar to Epsilon, than that value has almost all digits truncated away and so a relative error of almost 99,99%" (still not an arbitrary number). wich makes more sense.


    ___

    if "Epsilon" can't be changed for not breaking existing code, I suggest adding at least following 2 numbers, and then update current documentation.

    Mathf.SmallesPositiveFloat (currently Mathf.Epsilon)
    Mathf.MachinePrecision (1/2^23 on x86 machines)

    Both numbers can be estimated at runtime using binary search, so no need to hardcode them in documentation or in the engine. who need to know those values, need to query runtime informations, not hardcoded values anyway. I was lucky enough to see "1.40E-45" as current value in MonoDevelop (seeing a value means it is hardcoded) and that saved me lot of time debuggin because such small value was clearly wrong.

    routine:

    Code (csharp):
    1. float eps= 1.0f;
    2.  
    3.         do {
    4.            eps /= 2.0f;
    5.         }
    6.         while (1.0f+eps != 1.0f);
    7.  


    Cheers.
     
    Last edited: Mar 27, 2014
    Tymianek likes this.
  2. Mloren

    Mloren

    Joined:
    Aug 20, 2011
    Posts:
    83
    I just encountered what might be a related problem.

    I have some floating point math that ends up becoming 0.2f / 0.2f, producing the result 0.99999999...
    I need to convert this to an approximate integer and thought a good solution would be:
    Code (CSharp):
    1. int nIndex = (int)(fResult + Mathf.Epsilon);
    However the result of this before the cast was still 0.99999999... so it made no difference.

    Epsilon seems too small to be useful.
     
  3. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    I agree with all. And I propose Approximately (a, b, epsilon) overload, so you can use any value for epsilon you want. Or something you can configure in the project settings, maybe.

    I normally use 1E-06 as Epsilon in other projects in C++.