Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re^2: Old random number generator

by Pascal666 (Scribe)
on May 10, 2020 at 02:45 UTC ( #11116635=note: print w/replies, xml ) Need Help??


in reply to Re: Old random number generator
in thread Old random number generator

Wow. Thank you. Yes, I need a PRNG that outputs the same numbers as the old one. If I can implement it in Perl so that I don't have to worry about it ever changing again and it is the same on multiple platforms, awesome!

winrand()/(1<<15) does appear to output the correct test numbers with my test seeds. Unfortunately, I can't figure out how to use winrand(EXPR) the same way I would use rand(EXPR) ("returns a random fractional number greater than or equal to 0 and less than the value of EXPR").

For example, srand 0;print int(rand(99)) for 0..9 must always yield 023647263525973192.

Replies are listed 'Best First'.
Re^3: Old random number generator
by syphilis (Bishop) on May 10, 2020 at 04:26 UTC
    For example, srand 0;print int(rand(99)) for 0..9 must always yield 023647263525973192

    This outputs correctly for me:
    use warnings; use strict; my_srand(0); print int(my_rand(99)) for 0..9; sub my_srand { use Win32::API; my $srand = Win32::API::More->new( 'msvcrt', 'void srand(unsigned int seed)' ) or die "Error: ".Win32::FormatMessage(Win32::GetLastError()); $srand->Call($_[0]); } sub my_rand { my $rand = Win32::API::More->new( 'msvcrt', 'int rand()' ) or die "Error: ".Win32::FormatMessage(Win32::GetLastError()); return int(($rand->Call()) * $_[0] / 32767); }
    It outputs 023647263525973192
    The only problem is that it calls my_srand and my_rand, but I gather that the requirement is that it instead call srand and rand.
    I don't know how/if the builtin srand and rand can be overridden to point to my_srand and my_rand.

    Cheers,
    Rob
      Thank you. I don't mind calling my_srand and my_rand (no need to override srand and rand), but I would prefer a solution that works on Linux as well. The * $_[0] / 32767 part appears to be what I needed. print int(winrand()*99/32767) for 0..9 appears to work beautifully. Thank you everyone for your assistance!
        but I would prefer a solution that works on Linux as well

        On Linux, I'm finding that the behaviour hasn't changed. That is, when I run:
        perl -e 'srand(0); print int(rand(99)) for 0 .. 9'
        on Ubuntu, I get 1674986577768368673 from (current) perl-5.30.0 all the way back to perl-5.6.2.

        Or do you mean that you want the output of the one-liner to also be 023647263525973192 on Linux ?
        That could be tricky ... I'm not sure what that might involve.

        Here's an Inline::C version that does as you want on Windows - but produces a different sequence of numbers (83397779901933762754) on Ubuntu, where RAND_MAX is 2147483647.
        use strict; use warnings; use Inline C => <<'EOC'; SV * max_rand() { return newSViv(RAND_MAX); } void my_srand(int seed) { srand(seed); } SV * my_int_rand(IV limit) { return newSViv(rand() * limit / RAND_MAX); } SV * my_float_rand(IV limit) { return newSVnv((NV)rand() * limit / RAND_MAX); } EOC print "RAND_MAX is: ",max_rand(), "\n"; my_srand(0); print my_int_rand(99) for 0 .. 9; #print int(my_float_rand(99)) for 0 .. 9;
        Annoyingly on Ubuntu, although perl's rand() output seems constant across different versions of perl, it differs from the output of that script.

        Another possibility is that Math::Random might provide the functionality you seek. (I took a quick look, couldn't find anything helpful, and gave up ... but I didn't check it out rigorously.)

        Cheers,
        Rob
Re^3: Old random number generator
by choroba (Archbishop) on May 11, 2020 at 22:42 UTC
    #!/usr/bin/perl use warnings; use strict; { my $seed = 0; sub win_srand { $seed = shift } sub win_rand { my ($max) = @_; $seed = ( 214013 * $seed + 2531011 ) & 0xFFFFFFFF; return $max * (($seed >> 16) & 0x7FFF) / (1 << 15) } } win_srand(0); print int(win_rand(99)) for 0..9; # 023647263525973192.
    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (3)
As of 2020-10-24 00:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My favourite web site is:












    Results (242 votes). Check out past polls.

    Notices?