Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

random question

by perlaintdead (Scribe)
on Sep 08, 2013 at 07:39 UTC ( #1052881=perlquestion: print w/ replies, xml ) Need Help??
perlaintdead has asked for the wisdom of the Perl Monks concerning the following question:

I posted a very simple (and apparently bad) RNG and got a lot of good advice so here is my next shot at an RNG. Only problem is the numbers start too repeat after 5 iterations. not exactly a finished product and will try to make the seed more random latter but for now i just need to know why it repeats.

fixed
use warnings; use strict; use Digest::SHA 'sha384_hex'; my $randseed; my $randNum; my $salt = "salty"; print RandomMutation()."\n" for 0..100; sub RandomMutation{ $randseed = trim( convertToAscii( sha384_hex( crypt( rand(100000), + $salt) . localtime()) ) ); srand( $randseed ); $randNum = int rand 10000; $salt = trim( ( ( ( ($randNum / 2) + ($randseed * 1.427) + ($$ * 4 +) ** 2)) * 1.618) ); return $randNum; } sub convertToAscii{ my $convertToAscii = shift; my $ConvertedAscii = ""; foreach(split //, $convertToAscii){ $ConvertedAscii = $ConvertedAscii . ord $_ ; } return $ConvertedAscii; } sub trim{ my $TrimNum = shift; $TrimNum = substr $TrimNum, 5, 9; return $TrimNum; }

Comment on random question
Download Code
Re: random question
by kcott (Abbot) on Sep 08, 2013 at 08:22 UTC

    G'day perlaintdead,

    "I posted a very simple (and apparently bad) RNG and ..."

    A link to that would have been useful. Is Random Number Generator what you're referring to?

    Have you read rand and srand? Have you looked at the four CPAN modules that both of those have links to (at the end of their documentation)? Have you looked at the source code of those modules? Have you you followed up on the other advice given previously?

    Change

    print RandomMutation()."\n" for 0..100;

    to

    print RandomMutation()."\n" for 0..5;

    Add print statements throughout your code to see what's causing the repetition.

    -- Ken

      yes that was the one i did before. I looked into the modules and ran into so errors trying to install them (I kind of want to make my own RNG anyways AKA the hard way)

      Just read through both docs on srand and rand (for the 3rd or 4th time). the only thing i can thing of is multiple implicit calls to srand() but i try'd putting srand($salt) in the first line of the RandomMutation sub to no avail.

Re: random question
by perlaintdead (Scribe) on Sep 08, 2013 at 08:48 UTC

    what's weird is if i don't force scalar context it returns 10

      What do you mean by "if i don't force scalar context"? You are not "forcing" scalar context anywhere in your script?

      CountZero

      A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      My blog: Imperial Deltronics
Re: random question
by CountZero (Bishop) on Sep 08, 2013 at 09:14 UTC
    This is a subtle one!

    There are quite a few issues here with your approach.

    1. Read the docs about the srand function. It says clearly "Do not call srand() (i.e., without an argument) more than once per process. The internal state of the random number generator should contain more entropy than can be provided by any seed, so calling srand() again actually loses randomness.". Therefore, it is of no use to reseed the random number generator unless you can guarantee that your seed is more random (has a higher entropy) than Perl's internal random number function.
    2. Did you try looking at the values of $randseed? It is critically important that they are highly random otherwise your call to srand is useless. What do you notice? Indeed, $randseed is always of the form SCALAR(0x281734c) and the hex-part will repeat after a while (after 11 turns on my computer, I think that has to do with reclaiming memory.) That gives you a very very low entropy. If you delete the backslash before the calls to the trim subroutine, it should improve the randomness.
    3. Only, actually it doesn't. Now you get the same random number after a few turns through the loop. The reason is that you try to be too clever. After the call to convertToAscii you get a loooong string of more than 200 characters of which you take the first 40 and you feed that to the srand function. But that is way above the capacity of srand. Look at the return value of srand. It will be 4294967295 (on my PC, it may perhaps be different between 32 and 64 bit Perl); ALWAYS! Because that is the maximum value srand accepts. So it is much better to take only a 9 digits string out of the result of convertToAscii, somewhere from the middle, which will give you a better seed value. Of course, you should really run some statistical tests to see whether all digits have an equal chance of being generated to make sure it is a good idea.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics

      Excellent points. I’ll add one more observation:

      The call to time() is presumably there to add entropy (randomness). But time returns the number of seconds since the epoch; and for a run of 101 values, the script completes in less than a second, so time() returns at most two different values! This adds almost nothing to the randomness of the result.

      I’m no mathematician, but I’d be surprised if the output of the algorithm being tried (when properly debugged) is any more “random” than Perl’s out-of-the-box equivalent:

      print int(rand(1e4)), "\n" for 0 .. 100;

      (Note that the first call to rand implicitly calls srand here.)

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

        The invocation of time() was just a stand in for something with more entropy. I really wasn't worried about that until i debuged it.

      I'm running at 64x and srand takes 19 chars

        Very well, but that is still less than half the length of the data you feed it.

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

        My blog: Imperial Deltronics
Re: random question
by Eily (Hermit) on Sep 08, 2013 at 12:50 UTC

    Since each of your variables depends of the result of an operation on an other, and since time doesn't do much (because the value of localtime only changes every second as expressed by Athanasius), and since you reset srand each time you call your function, I would be surprised if you didn't end with a loop very fast. Because if you get the same randseed twice, rand will give you the same numbers, and so you'll go through exactly the same list of numbers until the value of localtime changes.

    That's what you get for calling srand with the ouput of rand:

    eval { $n = int rand(20); srand $n; print $n.' ' } for (1..10)
    13 9 0 3 15 4 13 9 0 3

    You just put additional layers to that problem, and a restart every second.

    As for your toASCII sub, have a look at pack, unpack, and the perlpacktut.

    My advice: if you want to make your own RNG: do go own. But do it from scratch, do not use rand, because that's actually what does all the work in your programs, and it prevents you to see the flaws in what you do. If you try and make your own RNG, and use it for a large scale number generation, you'll learn far more than trying to improve something that's possibly better than whatever you may achieve.

Re: random question
by Anonymous Monk on Sep 08, 2013 at 14:46 UTC
    I'm finding a random-number generator that relies on the built-in rand() and srand() quite odd. As the others have told you, you should not call srand() more than once in the program, and it's probably better to not call it at all! (Perl has done that for you already.)

    Anyway, here's a simple one that returns numbers in the range 0..65535:

    use Digest::SHA 'sha384_hex'; my $rng = generate_rng('salty' . localtime() . $$); print $rng->(), "\n" for 0..100; sub generate_rng { my $seed = shift; return sub { $seed = sha384_hex($seed); my $rnd = hex(substr($seed, 0, 4)); return $rnd; }; }

    For further study, you might want to look at OpenBSD's rand() which is about as simple as it gets. (It's also a poor one; its use is discouraged.)

      I think there's a minuscule probability that this RNG leaves (at least) one number never to generate, shortening its ideal cycle. Potential fix:
      sub generate_rng { my $seed = shift; my $count = 0; return sub { $seed = sha384_hex($seed . $count++); my $rnd = hex(substr($seed, 0, 4)); return $rnd; }; }

      Take my methods with a grain of salt since I'm an amateur at best in this subject -- I wouldn't know a bad RNG from a good one.

      Anyway, it appears that the OP is trying to increase the randomness of rand() by various voodoo methods. This is a futile task and he's much more likely to worsen it by making it more biassed. For example, a lot of newbies try to out-random random by saying rand() + rand() and getting a triangular distribution as a result.

Re: random question
by 5mi11er (Deacon) on Sep 08, 2013 at 21:11 UTC
Re: random question
by Preceptor (Chaplain) on Sep 09, 2013 at 16:01 UTC

      WOW dat RNG is 1337. It has ULTRA YOLO SWAG! here' a PERL version

      sub mostRandom{ return 4; }
        Based on your previous attempts at random number generation, I don't trust that you rolled the dice correctly.

        I got a 5, btw. Yours should match.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1052881]
Approved by kcott
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (11)
As of 2014-09-16 12:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (17 votes), past polls