Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Rand() with ?log10? distribution?

by BrowserUk (Patriarch)
on Jun 07, 2013 at 02:17 UTC ( [id://1037549]=perlquestion: print w/replies, xml ) Need Help??

BrowserUk has asked for the wisdom of the Perl Monks concerning the following question:

I want a rand function that produces lots of small numbers and a few big ones.

Say twice as many 0-9, as 10..99. And twice as many 0-99 as 100-999,. Etc.

Feels like log10 should be in there somewhere. Or maybe 10**something.

Note: I'm not looking for a function embedded in one of the big Math::* C libraries, as I will almost certainly want to tweak the distribution.


With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re: Rand() with ?log10? distribution?
by primo (Scribe) on Jun 07, 2013 at 03:39 UTC

    It won't be exactly a log 10 distribution, but rand()**2 * $max would probably be close to what you're looking for.

    For example:

    $rand_max = 1025; sub my_rand{ $rnd = rand; return int($rnd*$rnd * $rand_max); } @a = (); for(1..100000) { $n = my_rand(); $a[$n]++; } $i = 1; while($i <= 1024) { print "$i: ", $a[$i], $/; $i = $i*2; }

    will produce a distribution similar to this:

    1: 1338 2: 913 4: 718 8: 526 16: 397 32: 280 64: 195 128: 137 256: 99 512: 65 1024: 42

    If the curve is too steep (or not steep enough), you can adjust the exponent to 1.5, or 2.5 etc., instead of 2.

      We have a winner! sub primo2{ int( rand() ** 4 * $_[0] ) } Thanks.

      I came up with a few of my own:

      sub xx2{ int( 2**( 2**( rand() * logN( $_[0], 2 ) ) ) ) } sub xx10{ int( 10**( 10**( rand() * logN( $_[0], 10 ) ) ) ) } sub xx20{ int( 20**( 20**( rand() * logN( $_[0], 20 ) ) ) ) } sub xx100{ int( 100**( 100**( rand() * logN( $_[0], 100 ) ) ) ) }

      which I actually prefer to your original because they drop faster at the beginning but don't dip so low at the end, but they are computationally expensive and require the upper limited supplied as a log.

      Then I tried varying the exponent on yours, and found its ease of tunability the winning feature. Many thanks.

      graph (The above 4 are red, blue, green and cyan respectively, your original(^2) is magenta, and my chosen variation on it (^4) is yellow.)


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Rand() with ?log10? distribution? (math)
by tye (Sage) on Jun 07, 2013 at 03:55 UTC
    10**( log(1/(1-rand()))/log(2) ) - 1

    [Update: You may want to shorten the range if you get too many small (0.x) values or values that are too large. Replace 1-rand() with, for example .9-.8*rand().]

    10**( -log(1-rand())/log(2) ) - 1 # (same thing) (1-rand())**(log(.1)/log(2)) - 1 # (same thing)

    - tye        

    I'd show the (interesting) derivation, except the more words I include in a reply to you, the more likely the whole thing will turn ugly.

      Thanks.

      I didn't use this because: I couldn't work out how to set an upper limit; and the two-factor tuning is quite difficult, relative to the single factor tuning of primos solution.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Rand() with ?log10? distribution?
by v-zor (Initiate) on Jun 10, 2013 at 01:31 UTC
    You would need a nextInt function as in Java or Python, docs are here http://docs.python.org/2/library/random.html You can call python or write one with a $randomnumber * $x or $randomnumber + $x.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1037549]
Approved by Athanasius
Front-paged by Athanasius
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (4)
As of 2024-03-29 08:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found