Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. The 2022.2 beta is now available for testing. To find out what's new, have a look at our 2022.2 feature highlights.
    Dismiss Notice
  3. We are updating our Terms of Service for all Unity subscription plans, effective October 13, 2022, to create a more streamlined, user-friendly set of terms. Please review them here: unity.com/legal/terms-of-service.
    Dismiss Notice
  4. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice
  5. Join us on Thursday, September 29, for a day with Unity's SRP teams here on the forum or on Reddit, and discuss topics around URP, HDRP, and the Scriptable Render Pipeline in general.
    Dismiss Notice
Dismiss Notice
Submit bug reports tagged with #Beta2022Win_Unity when you encounter unknown issues while testing the 2022.2 betas for a chance to win a year of Unity Pro. For more information, have a look at our Beta Sweepstakes Announcement.

Discussion Weird behavior when generating random floats/doubles

Discussion in 'Data Oriented Technology Stack' started by CookieStealer2, Aug 8, 2022.

  1. CookieStealer2

    CookieStealer2

    Joined:
    Jun 25, 2018
    Posts:
    98
    Consider this, here I generate a float in the interval [float.MinValue, float.MaxValue) and a double in the interval [double.MinValue, double.MaxValue):
    Code (CSharp):
    1. Unity.Mathematics.Random random = new Unity.Mathematics.Random(1);
    2.  
    3. float floatValue = random.NextFloat(float.MinValue, float.MaxValue);
    4. double doubleValue = random.NextDouble(double.MinValue, double.MaxValue);
    5.  
    6. UnityEngine.Debug.Log($"floatValue: {floatValue}");
    7. UnityEngine.Debug.Log($"doubleValue: {doubleValue}");
    It prints:
    The float value is OK, but why am I getting inf for the double?

    I tried tried running the code in a loop for 1000 iterations to see if it was because of a specific state of the generator. But no... I always get infinity for doubles and an actual value for the floats.

    Looking at the source code below it seems like I should get inf in both cases since the max - min will overflow.
    Code (CSharp):
    1.  
    2. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    3. public float NextFloat(float min, float max) { return NextFloat() * (max - min) + min; }
    4.  
    5. [MethodImpl(MethodImplOptions.AggressiveInlining)]
    6. public double NextDouble(double min, double max) { return NextDouble() * (max - min) + min; }
    7.  
    Yet it magically works for floats. Anyone know what's going on here?
     
  2. Arnold_2013

    Arnold_2013

    Joined:
    Nov 24, 2013
    Posts:
    128
    with (float.MaxValue - float.MinValue) = (3.40282347E+38 - -3.40282347E+38) = 2 * float.MaxValue. I would imagine there would be a error since the value does not fit in a float.

    Does it work if you take a more reasonable value for min and max?
     
  3. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    891
    First thing in such cases that I check is the debugger. "Stringifying" floating point values can do all sorts of things to them (ie formatting, truncating) without you knowing about it.
     
  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    891
    Hmmm seems persistent, I get the same "Infinity" result:

    upload_2022-8-8_13-40-52.png

    But of course, this seems correct:

    Code (CSharp):
    1. public double NextDouble(double min, double max) { return NextDouble() * (max - min) + min; }
    Code (CSharp):
    1. var doubleMaxMinusMin = double.MaxValue - double.MinValue;
    2. => +Infinity
    Subtracting the min from max leads to infinity because it goes outside the scope of double values. In other words, essentially the same as:

    MaxValue - (-MaxValue)
    or:
    MaxValue + MaxValue

    I suppose floats "survive" this because in a 64-bit operating system they are propagated to double internally on the CPU.
     
    Last edited: Aug 8, 2022
  5. CookieStealer2

    CookieStealer2

    Joined:
    Jun 25, 2018
    Posts:
    98
    This is the information I was looking for. Thanks, that explains it.
    Still, it seems like a pretty weird behavior. Would have expected infinity in both cases.
     
  6. CookieStealer2

    CookieStealer2

    Joined:
    Jun 25, 2018
    Posts:
    98
    It works fine if (max - min) is within the scope of double values.
     
  7. CookieStealer2

    CookieStealer2

    Joined:
    Jun 25, 2018
    Posts:
    98
    Just made some tests about the auto propagation of floats to double. The circumstances for when it happens seems to be very specific.

    These floats do not propagate to doubles, so we get infinity:
    Code (CSharp):
    1.  
    2. float float1 = (float.MaxValue - float.MinValue) + float.MinValue; // Infinity
    3.  
    4. float float2 = FuncA(); // Infinity
    5.  
    6. public float FuncA()
    7. {
    8.     return (float.MaxValue - float.MinValue) + float.MinValue;
    9. }
    10.  
    But this one do and we get a valid float:
    Code (CSharp):
    1.  
    2. float float3 = FuncB(float.MinValue, float.MaxValue); // 3.40282347E+38
    3.  
    4. public float FuncB(float min, float max)
    5. {
    6.     return (max - min) + min;
    7. }
    8.  
    This is mind-boggling. I would expect all examples to behave the same.
     
unityunity