http://qs1969.pair.com?node_id=1211410

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

Hello all monks,

In the following code rand() doesn't even give me 52bit of data;
both MSB and LSBs are fixed !

what is the best way to get 64bit numbers ?

0000000000000000010111100101110000011011100101010001000000001111 00005 +E5C1B95100F 0000000000001100111011111010100001011001101001100011011101111111 000CE +FA859A6377F 0000000000000011001010100001010110101011101000101010001000101111 00032 +A15ABA2A22F 0000000000000110110100001111000101010110001101100010111100011111 0006D +0F156362F1F 0000000000001101001011001010011110010100111010001101000101001111 000D2 +CA794E8D14F 0000000000000101110101011101011111101000111011101111111110111111 0005D +5D7E8EEFFBF 0000000000000001000001010001000100101100100010010110010101101111 00010 +5112C89656F 0000000000001111110001100010010000001010111000101101000101011111 000FC +6240AE2D15F 0000000000000100100100001010101010101111001011110110011010001111 00049 +0AAAF2F668F 0000000000001100100011011000010010011010000101000000101111111111 000C8 +D849A140BFF 0000000000001101000011001100011010101101010100010001110010101111 000D0 +CC6AD511CAF 0000000000000010100111010110010110111101100011110101011110011111 00029 +D65BD8F579F 0000000000000000001100001110001000000110010000100000111111001111 00003 +0E206420FCF 0000000000000101001111111000100011111000000101011001110000111111 00053 +F88F8159C3F 0000000000000100100110101110000010010110100101010000011111101111 00049 +AE0969507EF 0000000000000100111011101101111101110011110101100000000111011111 0004E +EDF73D601DF 0000000000000110110111111000000010010010010011100000110100001111 0006D +F80924E0D0F 0000000000000111011111011100100001010101101101111111000001111111 00077 +DC855B7F07F 0000000000001110110001011111000001110111011001000110011100101111 000EC +5F07764672F 0000000000001101011110001010000111001010101101010001000000011111 000D7 +8A1CAB5101F
#!/usr/bin/perl $|++; srand(54321); for (1 .. 20) { my $n = int rand(0xF_FFFF_FFFF_FFFF); printf "\r%064b %016X\n",$n,$n; } exit $?;

Replies are listed 'Best First'.
Re: how to get a 64bit random number with rand() ?
by Tux (Canon) on Mar 21, 2018 at 15:02 UTC

    Note that this is not a (real) answer to your question, but some (side)notes ...

    If you use use strict; use warnings;, you would get this warning:

    Hexadecimal number > 0xffffffff non-portable at test.pl line 9

    Of course with the name of your script and the location of that 0xf...

    But when using large numbers like that, I'd advice to use decimal notation instead of hexadecimal, just for portability.

    Than it depends on your perl being compiled with -Duse64bitint or another (default) option that causes IV's (perl internal integers) allow 64bit data. That is easy to check though:

    $ perl -V:ivsize ivsize='8'; $ perl -wle'print 1152921504606846975' 1152921504606846975 $ perl -wle'printf "%x\n", 1152921504606846975' fffffffffffffff

    Compare to a perl with 32bit IV's:

    $ gperl32 -V:ivsize ivsize='4'; $ gperl32 -wle'print 1152921504606846975' 1.15292150460685e+18 $ gperl32 -wle'printf "%x\n", 1152921504606846975' ffffffff

    Maybe this helps on the short term:

    use 5.18.2; use warnings; $|++; srand 54321; say "One rand"; for (1 .. 20) { my $n = int rand 1152921504606846975; printf "\r%064b %016X\n", $n, $n; } say "Two rands"; for (1 .. 20) { my ($n1, $n2) = map { int rand 0xffff_ffff } 0, 1; my $n = unpack "Q>", pack "L>L>", $n1, $n2; printf "\r%064b %016X\n", $n, $n; }

    ->

    One rand 0000000001011110010111000001101110010101000100000000111111111111 005E5 +C1B95100FFF 0000110011101111101010000101100110100110001101110111111111111111 0CEFA +859A6377FFF 0000001100101010000101011010101110100010101000100010111111111111 032A1 +5ABA2A22FFF 0000011011010000111100010101011000110110001011110001111111111111 06D0F +156362F1FFF 0000110100101100101001111001010011101000110100010100111111111111 0D2CA +794E8D14FFF 0000010111010101110101111110100011101110111111111011111111111111 05D5D +7E8EEFFBFFF 0000000100000101000100010010110010001001011001010110111111111111 01051 +12C89656FFF 0000111111000110001001000000101011100010110100010101111111111111 0FC62 +40AE2D15FFF 0000010010010000101010101010111100101111011001101000111111111111 0490A +AAF2F668FFF 0000110010001101100001001001101000010100000010111111111111111111 0C8D8 +49A140BFFFF 0000110100001100110001101010110101010001000111001010111111111111 0D0CC +6AD511CAFFF 0000001010011101011001011011110110001111010101111001111111111111 029D6 +5BD8F579FFF 0000000000110000111000100000011001000010000011111100111111111111 0030E +206420FCFFF 0000010100111111100010001111100000010101100111000011111111111111 053F8 +8F8159C3FFF 0000010010011010111000001001011010010101000001111110111111111111 049AE +0969507EFFF 0000010011101110110111110111001111010110000000011101111111111111 04EED +F73D601DFFF 0000011011011111100000001001001001001110000011010000111111111111 06DF8 +0924E0D0FFF 0000011101111101110010000101010110110111111100000111111111111111 077DC +855B7F07FFF 0000111011000101111100000111011101100100011001110010111111111111 0EC5F +07764672FFF 0000110101111000101000011100101010110101000100000001111111111111 0D78A +1CAB5101FFF Two rands 0110111011001000100010011001000010011000011110001101000001011011 6EC88 +9909878D05B 1000011111110001011001111000011100001110111101111100100010001100 87F16 +7870EF7C88C 1011000100011111101001110011000101100011010110101001110101110011 B11FA +731635A9D73 1110001111001110010011000011100101001011111110010101000101001010 E3CE4 +C394BF9514A 1110001001010010001001100101001001010011000011001111000101011100 E2522 +652530CF15C 1111001101101100101000011110101010011011111101000110000011101110 F36CA +1EA9BF460EE 0011110101110110001011001101001110011110001101000111010011011010 3D762 +CD39E3474DA 1110010101011100001011111011000101010100110100110110010100001010 E55C2 +FB154D3650A 0001000100010110101111100011110000100000111001010100000101000011 1116B +E3C20E54143 1001010000111100010000111000111010100100101100111001100011011000 943C4 +38EA4B398D8 1101101010011010011001010001001100110100111010100111000101000001 DA9A6 +51334EA7141 0101010111110100011011011110000100101100011001110000110110100100 55F46 +DE12C670DA4 0101011101011010100111010111001010011010111011110111100111010110 575A9 +D729AEF79D6 1110111111111001000000000001111001110000011001000101010101100110 EFF90 +01E70645566 0111010100101110110101001101001101110110111101111000111110100000 752ED +4D376F78FA0 1010110111001100010000101100000111011001001100111011001110110010 ADCC4 +2C1D933B3B2 0110010100000111000100110010110101100110100011111001110001011110 65071 +32D668F9C5E 1000010010001000100101101000000010100011000000111111100011010100 84889 +680A303F8D4 1001011101011111101000010100010000010010111010111000100010110010 975FA +14412EB88B2 1001001001001110111101001100000001101010000011110110101100110110 924EF +4C06A0F6B36

    Enjoy, Have FUN! H.Merijn
Re: how to get a 64bit random number with rand() ?
by thanos1983 (Parson) on Mar 21, 2018 at 12:35 UTC

    Hello iglake,

    Take a look on an older question with multiple different answers to your problem 64 bit random numbers.

    Hope this helps, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!
      thanks it does help !
Re: how to get a 64bit random number with rand() ?
by BrowserUk (Patriarch) on Mar 21, 2018 at 18:06 UTC

    Here's one way on a 64-bit capable build, provided your prng can produce at least 8-bit rands:

    sub rand64{ unpack 'Q', pack 'C8', map rand(256), 1 .. 8; } for(1..10){ my $rand64 = rand64(); printf "%64s %16s %I64U\n", unpack( 'b64', pack( 'Q', $rand64 ) ), unpack( 'H16', pack( 'Q', $rand64 ) ), $rand64; } 1010111111000000011010001011001101101010011001011110100101011101 f5031 +6cd56a697ba 13445398104276075509 1011010011110001101111011011100010001000001100000001011101111110 2d8fb +d1d110ce87e 9144572311028731693 1100000000001011011000101111011110001110110110001110000000101001 03d04 +6ef711b0794 10666524418609958915 1000101001111110010101010010011101000111000011010101100000110110 517ea +ae4e2b01a6c 7789732994036170321 0010010000011010010011110001100000111110001011000100110111110011 2458f +2187c34b2cf 14966082219304704036 1111100110000001010110000110011011011100010010001001000100101101 9f811 +a663b1289b4 13008949044961771935 1001111000111111101110010111001111010011011111001110101110101100 79fc9 +dcecb3ed735 3879638649068715129 0000010011010010001110011101111101011111001001110101001011100101 204b9 +cfbfae44aa7 12054699119224834848 1110111000010100001101010110011111010011111011000100010111100011 7728a +ce6cb37a2c7 14385121508662716535 0011110011100110111011000101100110100100100110101101011101011000 3c673 +79a2559eb1a 1939742082549114684

    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". The enemy of (IT) success is complexity.
    In the absence of evidence, opinion is indistinguishable from prejudice. Suck that fhit
Re: how to get a 64bit random number with rand() ?
by LanX (Saint) on Mar 21, 2018 at 12:44 UTC
      yes that is what I ended up doing, thanks !

        Be careful how you combine them. Done right its fine; done wrong and it exacerbates any limitations in the 32-bit rands.


        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". The enemy of (IT) success is complexity.
        In the absence of evidence, opinion is indistinguishable from prejudice. Suck that fhit
Re: how to get a 64bit random number with rand() ?
by bliako (Monsignor) on Mar 22, 2018 at 14:55 UTC

    Can't agree more with BrowserUk.

    Whatever you do always verify the statistical distribution of your method for producing random numbers. In order to do that you need to produce a large bunch of these random numbers and plot a histogram of their values or, much more accurate, run a test for verifying the distribution. Here is a test for a discrete distribution, e.g. dice numbers: https://stackoverflow.com/questions/21204733/a-better-chi-square-test-for-perl

    Perl's rand() will, in theory, produce random numbers drawn from a uniform distribution: all values from 0 to 1 have equal probability to appear. The histogram of such a distribution is more-or-less a flat line (the equal probabilities). Provided that you draw *a lot* of random numbers you will be approximating that.

    Now if you *add* two rand() values in order, for example, to get a 64-bit random value you will find that the histogram of the numbers you get is not a flat line anymore but resembling more of a bell-curve, the trademark of a Gaussian (aka Normal) distribution. I would love to play poker against a machine which uses this method ...

    Here is some code to demonstrate this:
    #!/usr/bin/env perl use strict; use warnings; use Statistics::Histogram; my $num_bins = 50; my $use_linear_axes = 1; srand(1234); ### Produce a lot of random numbers: # 1) expecting a flat line (uniform distribution): my @x = map { rand() } 1..1000000; # 2) sum of two rand() to get larger random number # - I am getting larger numbers and I am expecting a flat line. # - you wanna bet? my @y = map { rand()+rand() } 1..1000000; # Now draw the histograms of obtained random numbers: # 1) perl's rand is quite uniform, I see a flat line: print Statistics::Histogram::get_histogram(\@x, $num_bins, $use_linear +_axes); # 2) !!ouch - that hurt !! print Statistics::Histogram::get_histogram(\@y, $num_bins, $use_linear +_axes);

    Bottomline: I always wanted to ask Einsten to clarify whether "dice" in his famous "God does not play dice" is plurar or singular. I guess I will never know although maybe 60 years ago dice did have the singular of die. If God plays with a single dice his or her distributions will be Uniform (the flat lines). However, if God plays with two dice (and sums up the two rands) his/her distributions will be Gaussian (the bell shape) and that makes a lot of difference for the Universe.

    bliako
      I always wanted to ask Einsten to clarify whether "dice" in his famous "God does not play dice" is plurar or singular.
      God will have an infinite-sided die (a sphere), and can therefore get any real number with only 1 throw.

      -QM
      --
      Quantum Mechanics: The dreams stuff is made of

        the distribution the number is drawn from is what counts. Uniform then unless the sphere is not honest.

        It is obvious that Einstein thought God to be singular (as per LanX) for the simple reason that a multitude of Gods would probably combine their random numbers which would result in a Gaussian again...

        Polytheism results in an extremely biased (and predictable) Universe.

        bliako
      AFAIK he said "Gott würfelt nicht!" *

      "würfeln" is a verb for playing with dice without numerus for the object. ("God is not dicing!"° if you want)

      His English was so rudimentary, that his assistants in Princeton had to be fluent in German.

      But I'm sure he supposed God to be singular...

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Wikisyntax for the Monastery

      *) according to wikipedia from 1926

      °) "to dice" exists at least in Shakespearian English and Game of Thrones.

      Now if you *add* two rand() values in order, for example, to get a 64-bit random value
      You have omitted a little bit of detail that was not omitted in BrowserUk's warning: the context was combining two 32-bit values to obtain a 64-bit value.

      Can you please elaborate on how it is possible to ADD two 32-bit numbers — of any origin, not necessarily rand() — and arrive at a value in 64-bit range?

        my point lies somewhere else, but you are correct:

        adding two 32-bit numbers may get you to, at most, a 33-bit number.

        Read that as "add thirty-two 32-bit rands()" (Gaussian distribution) or "multiply two 32-bit rands()" (uniform-product distribution).

        Adding is just one form of combining two values but it's perfect to demonstrate the caveats of "combining" rand()s and that not all forms of "combining" rand()s lead to the desirable effect.

        bliako
Re: how to get a 64bit random number with rand() ?
by Anonymous Monk on Mar 21, 2018 at 20:32 UTC

    If you're on Linux and need a block of randomness of decent quality, you may defer to system's random generator. Tools like shuf use the same under the hood.

    #! /usr/bin/perl use strict; use warnings; sub rnd_bytes { local $/ = \( shift || 8 ); open my $fh, '<', '/dev/urandom'; scalar <$fh> } for my $n (unpack "Q*", rnd_bytes(20 * 8)) { printf "\r%064b %016X\n",$n,$n; }

Re: how to get a 64bit random number with rand() ?
by Anonymous Monk on Mar 21, 2018 at 13:18 UTC
    It sounds to me like you need a cryptographically secure PRNG such as Math::Random::Secure or Crypt::Random . . . "Garden variety" PRNGs are good enough for statistics sampling only, or the occasional game.

      sundial, there is nothing in the OPs post that suggests, hints or alludes to a requirement for the huge additional costs and complexity of a cryptographic PRNG.

      You're just making shit up again, and spewing out regurgitated snippets of advice by other people, that you obviously have no understanding of.


      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". The enemy of (IT) success is complexity.
      In the absence of evidence, opinion is indistinguishable from prejudice. Suck that fhit
        Let's be fair. 'Anonymous Monk' has alerted the OP that in some cases, more powerful tools are required and are available. Potentially, this could be the most important post so far.
        Bill
          A reply falls below the community's threshold of quality. You may see it by logging in.