in reply to Re^2: inclusive rand
in thread inclusive rand

> Thanks. I guess that'd work if I knew what precision rand uses.

you can't go to full precision.

Please learn the basics of floating numbers and stop randomly changing your posts.

Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
Je suis Charlie!

Replies are listed 'Best First'.
Re^4: inclusive rand
by msh210 (Monk) on Mar 13, 2017 at 13:05 UTC

    If I can't go to full precision, then I don't see how the solution you (and another) proposed, subdividing the interval from 0 to a large integer, is the same as inclusive rand. It will always be less precise, i.e. choosing among fewer numbers. No?

    $_="msh210";$"=$\;@_=@{[split//,uc]}[2,0];$_="@_$\1";$\=$/;++$_[0]for$...1;print lc substr crypt($_,"@_"),1,6
      in reality one wants random results which are equally distributed.

      This consequently means one decides how big the result set is in order to define the requested probability of one single element of this set (which is actually only approximated) and some other criteria like distribution (also approximated)

      If ... for any applications which are beyond my experience ... the resolution of the build in rand is not enough, you'd simply use another rand-module from CPAN in conjunction with something like bignum

      Now ... asking for equally distributed real numbers is nonsensical, because you can't tell the expected probability of say pi.

      And even if you used a natural random number generator ... like by measuring radio activity ... you'd finally be confronted with the limits of quantum mechanics. There is no unlimited precision.

      We live in reality, and computers are build into the real world (i.e. this universe)

      This means a random number is always ultimately some integer in disguise.

      Sorry your question can't be answered otherwise because it would become unreal.

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

      > It will always be less precise, i.e. choosing among fewer numbers. No?

      even if you don't want to use a self defined precission you could try this

      perl -Mposix -E" say rand(1+1/2**47) for 1..20"

      So why 47?

      Just try and error on my system

      C:\Windows\system32>perl -E" say 1+1/2**47;" + 1.00000000000001 C:\Windows\system32>perl -E" say 1+1/2**48;" 1

      I'm too lazy to figure out how exactly the limits of the mantissa is used internally and where the caveats are.

      And taking the rounding errors in these into assumption this shouldn't matter much. (as BUK mentioned under windows before 5.20 rand is limted to 15 bits only.)

      The practical value of this is too small to justify more elaboration.

      update

      or alternatively to avoid floats and rounding errors

      C:\Windows\system32>perl -E"$r=int rand(1e15+1); say $r==1e15 ? 1 : sp +rintf '0.%015s', $r" 0.176483154296875

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

        The limit of the mantissa is the ULP. For a double-precision float typically used in perl, it's 2**-52 times the main power of two for the number:

        perl -MData::IEEE754::Tools=:all -le"$,=qq(\t); map { print $_, ulp($_ +) } @ARGV" 0.25 0.4 0.5 0.6 0.9 1 1.9 2 0.25 5.55111512312578e-017 0.4 5.55111512312578e-017 0.5 1.11022302462516e-016 0.6 1.11022302462516e-016 0.9 1.11022302462516e-016 1 2.22044604925031e-016 1.9 2.22044604925031e-016 2 4.44089209850063e-016

        This can also be seen in your 1+1/2**x by printing the underlying IEEE754, or by using a powers-of-two representation of the float, or by always using %.16f

        perl -MData::IEEE754::Tools=:all -e"printf qq(%-3d %-32.32s 0x%-16s %. +16f %s\n), $_, 1+1/2**$_, hexstr754_from_double(1+1/2**$_), 1+1/2**$_ +, to_dec_floatingpoint(1+1/2**$_) for @ARGV" 47 48 49 50 51 52 53 54 +55 56 47 1.00000000000001 0x3FF0000000000020 1.000000000000 +0071 +0d1.0000000000000071p+0000 48 1 0x3FF0000000000010 1.000000000000 +0036 +0d1.0000000000000036p+0000 49 1 0x3FF0000000000008 1.000000000000 +0018 +0d1.0000000000000018p+0000 50 1 0x3FF0000000000004 1.000000000000 +0009 +0d1.0000000000000009p+0000 51 1 0x3FF0000000000002 1.000000000000 +0004 +0d1.0000000000000004p+0000 52 1 0x3FF0000000000001 1.000000000000 +0002 +0d1.0000000000000002p+0000 53 1 0x3FF0000000000000 1.000000000000 +0000 +0d1.0000000000000000p+0000 54 1 0x3FF0000000000000 1.000000000000 +0000 +0d1.0000000000000000p+0000 55 1 0x3FF0000000000000 1.000000000000 +0000 +0d1.0000000000000000p+0000 56 1 0x3FF0000000000000 1.000000000000 +0000 +0d1.0000000000000000p+0000

        for numbers from 0.5 to 0.9999..., it's one better:

        perl -MData::IEEE754::Tools=:all -e"printf qq(%-3d %-32.32s 0x%-16s %. +16f %s\n), $_, 0.5+1/2**$_, hexstr754_from_double(0.5+1/2**$_), 0.5+1 +/2**$_, to_dec_floatingpoint(0.5+1/2**$_) for @ARGV" 47 48 49 50 51 5 +2 53 54 55 56 47 0.500000000000007 0x3FE0000000000040 0.500000000000 +0071 +0d1.0000000000000142p-0001 48 0.500000000000004 0x3FE0000000000020 0.500000000000 +0036 +0d1.0000000000000071p-0001 49 0.500000000000002 0x3FE0000000000010 0.500000000000 +0018 +0d1.0000000000000036p-0001 50 0.500000000000001 0x3FE0000000000008 0.500000000000 +0009 +0d1.0000000000000018p-0001 51 0.5 0x3FE0000000000004 0.500000000000 +0004 +0d1.0000000000000009p-0001 52 0.5 0x3FE0000000000002 0.500000000000 +0002 +0d1.0000000000000004p-0001 53 0.5 0x3FE0000000000001 0.500000000000 +0001 +0d1.0000000000000002p-0001 54 0.5 0x3FE0000000000000 0.500000000000 +0000 +0d1.0000000000000000p-0001 55 0.5 0x3FE0000000000000 0.500000000000 +0000 +0d1.0000000000000000p-0001 56 0.5 0x3FE0000000000000 0.500000000000 +0000 +0d1.0000000000000000p-0001 perl -MData::IEEE754::Tools=:all -e"printf qq(%-3d %-32.32s 0x%-16s %. +16f %s\n), $_, 1.0-1/2**$_, hexstr754_from_double(1-1/2**$_), 1-1/2** +$_, to_dec_floatingpoint(1-1/2**$_) for @ARGV" 47 48 49 50 51 52 53 5 +4 55 56 47 0.999999999999993 0x3FEFFFFFFFFFFFC0 0.999999999999 +9929 +0d1.9999999999999858p-0001 48 0.999999999999996 0x3FEFFFFFFFFFFFE0 0.999999999999 +9965 +0d1.9999999999999929p-0001 49 0.999999999999998 0x3FEFFFFFFFFFFFF0 0.999999999999 +9982 +0d1.9999999999999964p-0001 50 0.999999999999999 0x3FEFFFFFFFFFFFF8 0.999999999999 +9991 +0d1.9999999999999982p-0001 51 1 0x3FEFFFFFFFFFFFFC 0.999999999999 +9996 +0d1.9999999999999991p-0001 52 1 0x3FEFFFFFFFFFFFFE 0.999999999999 +9998 +0d1.9999999999999996p-0001 53 1 0x3FEFFFFFFFFFFFFF 0.999999999999 +9999 +0d1.9999999999999998p-0001 54 1 0x3FF0000000000000 1.000000000000 +0000 +0d1.0000000000000000p+0000 55 1 0x3FF0000000000000 1.000000000000 +0000 +0d1.0000000000000000p+0000 56 1 0x3FF0000000000000 1.000000000000 +0000 +0d1.0000000000000000p+0000

        Interesting ideas. Thanks!

        $_="msh210";$"=$\;@_=@{[split//,uc]}[2,0];$_="@_$\1";$\=$/;++$_[0]for$...1;print lc substr crypt($_,"@_"),1,6