Shop OBEX P1 Docs P2 Docs Learn Events
generating a random number in a certain range — Parallax Forums

generating a random number in a certain range

science_geekscience_geek Posts: 247
edited 2009-09-26 08:59 in Propeller 1
How would i go about generating a random number in a certain range, say between 0 and 255, i have looked in the manual at the "?" command but i dont think i fully get how it works. also is there a way to generate this random number to hit higher or lower numbers more frequently than others.

Comments

  • TimmooreTimmoore Posts: 1,031
    edited 2009-09-23 16:26
    ?
    gives you a random number +-2,147,483,648
    ?//255
    will give you a random no +-255
    ||(?//255)
    will give you a random no 0-255
  • ericballericball Posts: 774
    edited 2009-09-23 19:29
    @Timmoore - ? is a unary operator, it requires a variable.

    Var? returns the next random number in the LFSR sequence, and updates Var to that value so the next Var? returns a different random number. ?Var returns the previous number in the LFSR sequence. See page 159 in the Propeller Manual for more details.

    Because ? is based on an LFSR, the random number sequence will cycle through all 2^32 values before repeating a value (i.e. uniform distribution). If you want a non-uniform distribution, then you will need to perform some kind of operations using Var to bias the result as desired. (e.g. Result := ?Var / (>|Var+1) would produce an interesting zero biased non-uniform distribution.)

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Composite NTSC sprite driver: Forum
    NTSC & PAL driver templates: ObEx Forum
    OnePinTVText driver: ObEx Forum
  • ziplockziplock Posts: 9
    edited 2009-09-24 00:25
    To get a number within a certain range, do something like this:

    OBJ
       r : "RealRandom"
    
    VAR
       long anyNameValue
    
    PUB RandomGeneration
       r.start
       anyNameValue := r.random #> 0 <# 255
    
    



    anyNameValue is a placeholder. As it's name implies, use any name you want.

    In this line:
    anyNameValue := r.random #> 0 <# 255
    


    #> 0 sets the lowest generated number to 0, and <# 255 sets the highest generated number to 255.
    Of course, this is assuming that you are using the RealRandom object.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Hey! I'm Adam.
    But YOU can call me ziplock.

    Blog: braindrink.wordpress.com
    "The only problem with the gene pool is that there is no lifeguard." -David Gerrold
  • John AbshierJohn Abshier Posts: 1,116
    edited 2009-09-24 03:59
    ziplock, that will not be very random. You will get mostly 0s and 255s. I ran it for 100 values and got only 0s and 255s. You need to use the abs and mod functions.

    John Abshier
  • T ChapT Chap Posts: 4,223
    edited 2009-09-24 05:14
    Do the real random number, if the number exceeds the range you want it to fall in, use case with some formulas (/10, /100, /1000 etc) to get it into your range.

    ? is not really random btw
  • kwinnkwinn Posts: 8,697
    edited 2009-09-24 07:12
    You can also treat the 32 bit binary number as a value between 0 and 1, multiply it by the range you want, and add the offset you want.

    If you want a number between 256 and 511 take the 32 bit number returned by the random number generator, multiply it by 256, divide it by 4,294,967,295 (hex FFFFFFFF), and add 256 to it.
  • heaterheater Posts: 3,370
    edited 2009-09-24 09:39
    kwinn: I don't think that does what you want after taking 32 bit overflow and signed arithmetic of Spin into account.

    Multiply by 256 will overflow the 32 bit result for most of the initial random numbers. Leaving rrrrrr00 HEX, where "r" is a random hex digit. This number may be positive or negative.

    Divide by FFFFFFFF HEX is a divide by minus one which does not help.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    For me, the past is not over yet.
  • kwinnkwinn Posts: 8,697
    edited 2009-09-24 16:53
    heater, I did not mean to imply that it could be done by the signed arithmetic of spin, only as an illustration, and I did not describe it well. For 32 bit numbers you would need to use 64 bit arithmetic.

    Lets say you want a random number between 100 and 200 (a span of 101) and you have a random number algorithm that produces numbers from 0 to 1 (with a sufficient number of digits). If you take the random number produced, multiply it by 100 and round it to an integer you will end up with a number between 0 and 100. Add 100 and you have numbers in the range you want.

    In many cases a lot of the calculations can be done using binary arithmetic and shifts. The key concerns are having a random number generator that produces numbers with a large enough range and sufficient randomness, and maintaining precision during the calculations.
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2009-09-24 16:58
    I have used this for a while:
    PUB rand (maxv, minv)
    '' Return a psudo-random value between maxv and minv (inclusive).
      IF (minv > maxv)
        RETURN false
      IF (minv == maxv)
        RETURN maxv
    
      RETURN (||?cnt // ((maxv - minv) + 1)) + minv
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    April, 2008: when I discovered the answers to all my micro-computational-botherations!
  • science_geekscience_geek Posts: 247
    edited 2009-09-24 20:42
    thank you all for your replies, i tried Bobb Fwed's code and it does the job
  • mparkmpark Posts: 1,305
    edited 2009-09-26 05:24
    Bobb Fwed said...
    I have used this for a while:
    PUB rand (maxv, minv)
    '' Return a psudo-random value between maxv and minv (inclusive).
      IF (minv > maxv)
        RETURN false
      IF (minv == maxv)
        RETURN maxv
    
      RETURN (||?cnt // ((maxv - minv) + 1)) + minv
    


    If ?cnt ever evaluates to $8000_0000, the return value could be less than minv.

    Open question: can ?cnt ever be $8000_0000?
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2009-09-26 07:08
    mpark said...
    Bobb Fwed said...
    I have used this for a while:
    PUB rand (maxv, minv)
    '' Return a psudo-random value between maxv and minv (inclusive).
      IF (minv > maxv)
        RETURN false
      IF (minv == maxv)
        RETURN maxv
    
      RETURN (||?cnt // ((maxv - minv) + 1)) + minv
    


    If ?cnt ever evaluates to $8000_0000, the return value could be less than minv.

    Open question: can ?cnt ever be $8000_0000?

    Someone correct me, if I'm wrong. But that doesn't matter. The idea is maxv-minv gets the difference (which is the true range), then random number within the "range" is added by minv to produce the correct values.

    dif := maxv - minv + 1 ' get range
    rand := ||?cnt ' get random value greater or equal to 0 ($8000_0000 should just return 0 with the ||)
    val := rand // dif ' returns random value with the limited range
    val += minv ' returns value between maxv and minv (inclusive)
    
    


    Did that help at all...or is that just confusing for everyone.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    April, 2008: when I discovered the answers to all my micro-computational-botherations!

    Some of my objects:
    MCP3X0X ADC Driver Programmable Schmitt inputs, frequency reading, and more!
    Simple Propeller-based Database Making life easier and more readable for all your EEPROM storage needs.
    String Manipulation Library Don't make strings the bane of the Propeller, bend them to your will!

    Post Edited (Bobb Fwed) : 9/26/2009 7:19:41 AM GMT
  • mparkmpark Posts: 1,305
    edited 2009-09-26 07:27
    The problem is that you can't take the absolute value of $8000_0000 in 32 bits.
    ||$8000_0000 is $8000_0000. In decimal, ||-2147483648 is -2147483648 (still negative!).
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2009-09-26 08:59
    Ah...did not know that. That can be fixed by removing the || and replacing it with a ?cnt >> 1 -- probably the simplest fix.
    I have never noticed the method returning negative (or otherwise unexpected) numbers, but there is only a 1 in 2^32 chance...

    I have also used a slightly modified version where the address of a real_random long was passed to the method and replaces the pseudo random system...that's always nice to use. ...same fix would be needed for that one. Thanks for the info about the odd ?bug? with ||.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    April, 2008: when I discovered the answers to all my micro-computational-botherations!

    Some of my objects:
    MCP3X0X ADC Driver Programmable Schmitt inputs, frequency reading, and more!
    Simple Propeller-based Database Making life easier and more readable for all your EEPROM storage needs.
    String Manipulation Library Don't make strings the bane of the Propeller, bend them to your will!

    Post Edited (Bobb Fwed) : 9/26/2009 9:04:47 AM GMT
Sign In or Register to comment.