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. Join us on March 30, 2023, between 5 am & 1 pm EST, in the Performance Profiling Dev Blitz Day 2023 - Q&A forum and Discord where you can connect with our teams behind the Memory and CPU Profilers.
    Dismiss Notice

Discussion Random.Range int max is no longer exclusive

Discussion in 'Scripting' started by Josiah_Ironclad, Sep 15, 2022.

  1. Josiah_Ironclad

    Josiah_Ironclad

    Joined:
    Sep 24, 2019
    Posts:
    156
    I am using Unity 2021.3.7f1, and according to the documentation for 2021.3, the max value of Random.Range int is exclusive. upload_2022-9-15_1-17-55.png
    (the beginning of the highlighted part also has a typo)

    But I just did some random object generation with that in mind (I wanted maximum of 2 to spawn), and looky here.


    3 meat gameobjects.
    All I'm doing is putting the random number into a for loop checking "i < meatAmount" so for 3 meats it'd go "0, 1, 2" and then stop loop.
     
    Last edited: Sep 15, 2022
    hippocoder likes this.
  2. Josiah_Ironclad

    Josiah_Ironclad

    Joined:
    Sep 24, 2019
    Posts:
    156
    Well I feel stupid... Could a moderator please delete this thread? I don't really know how to seek them out to DM them.
    I honestly feel so embarrassed right now I don't even wanna say why.
     
    Last edited: Sep 15, 2022
    orionsyndrome and hippocoder like this.
  3. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Int or Float :D

    I'm just really dragging it out for fun...
     
  4. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    2,239
    Lol, it's okay. Range(float, float) was always inclusive. Range(int, int) was always exclusive.

    The reason for that is because of how random values are actually generated.
    I made a random RNG based on a permuted congruential generator (PCG) and basically you generate wild hashes that fill all the available value space of an integer. It's a binary noise, so to speak, and the issue is when you want to extract something meaningful with it, you then want to scale this noise from the range of 0-2^31 to a ranged mapping. If that range is integral, there is neat integer division trick where you compute a division remainder instead, and thus clamp it to the range (where the modulus becomes out of reach, i.e. exclusive), but if the range is a floating point, such as Random.value, then you have to divide the whole sausage with int.MaxValue (2^31), and so you'd have to have a number that is exactly 2^31 to return exactly 1.0f which happens in 1/2^31 cases. So the truth is, while the floating point range is inclusive, because you typically get well-distributed values so near to 1.0f (when they're near), they're almost as good as 1.0f itself. Range(float, float) just extrapolates from Random.value, or better said "interpolates".

    Random.value => _random_int / (float)int.MaxValue;
    Range(float min, float max) => min + Random.Value * (max - min);
    Range(int min, int max) => min + _random_int % (max - min);

    This is a naive approach ofc, there are techniques and techniques to improve on the integral distribution based on prime numbers.
     
    Last edited: Sep 15, 2022
    Josiah_Ironclad and hippocoder like this.
  5. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    2,913
    Actually using the modulo has a uniform distribution with the exception on the very last section unless your range is a power of two so the whole range divides without rest. The simplest solution when you need a fair random roll is to simply re-roll a new number if it falls in the last incomplete set.

    Just as an example if the range is 7, the highest signed integer value mod 7 is 1. So the last incomplete set only contains the number 0 and 1. So technically those have a slightly higher probability. Though with such a small range the difference would not really matter as there are over 300 million complete sets (0 - 6) and just one incomplete. However at larger ranges it becomes more of a problem. So by simply exluding the last incomplete set you get a perfect uniform distribution.
     
    hippocoder and orionsyndrome like this.
  6. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    2,239
    @Bunny83 something like that yes, though when you exclude a set, you lose a chunk of entropy (of course for large intervals). I forgot how exactly I solved this, it was per recommendation of someone smarter than me, armed with a suite of tools for random distribution analysis. I remember only spending a lot of time Monte-Carloing, making sure I didn't mess something up. but it was several years ago, I might do it again. if I do, I'll remember to post what the solution was exactly.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    32,369
    I used this for all my TRS-80 Model 100 games back in 1984.

    If you just called it and graphed the output it wasn't great.

    But if you called it a lot from all over your program, it actually did fantastically well, and I never "felt" like my games ever played twice or were predictable in any way.

    Code (csharp):
    1. ; easy cheesy random numbers on an 8085 CPU on the TRS-80 Model 100:
    2. ; uses contents of A and whatever HL happens to be pointing to at time of call
    3. RND:
    4.     PUSH    HL         ; preserve
    5.     ADC    (HL)
    6.     LD    HL,RR        ; first byte of random state
    7.     ADC    (HL)
    8.     LD    (HL),A
    9.     INC    HL            ; advance to next byte of random state
    10.     ADD    (HL)
    11.     LD    (HL),A
    12.     INC    HL            ; advance to next byte of random state
    13.     ADC    (HL)
    14.     LD    (HL),A
    15.     POP    HL
    16.     RET
    17.  
    18. RR    DS    3            ; 3 bytes of random state
    You can play it in any of the games prefixed with "VV" in my KurtMaster2D app. :)

    Apple iTunes: https://itunes.apple.com/us/app/kurtmaster2d/id1015692678
    Google Play (including TV): https://play.google.com/store/apps/details?id=com.plbm.plbm1

    OH YEAH! I forgot I opened sourced all this code years ago and you can see it all here, including built binaries of the above games to run on your TRS-80 Model 100.

    https://bitchin100.com/m100-oss/archive.html
     
    Last edited: Sep 15, 2022
  8. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    2,239
    Wow I wish anything from my 80's survived. My life is like a Winamp visualization, you know the shader where the buffer is constantly blurred and fading away.
     
    Anthiese and Kurt-Dekker like this.
  9. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Same, all my old stuff... probably gone </3
     
    Kurt-Dekker likes this.