XP is just a number PerlMonks

### inclusive rand

by msh210 (Scribe)
 on Mar 13, 2017 at 12:17 UTC Need Help??
msh210 has asked for the wisdom of the Perl Monks concerning the following question:

O Monks,

How can one generate a (pseudo)random number between 0 and 1, inclusive? I checked rand and the links it contains to other generators, as well as the Monastery's own search and Google, but all I've found is for random numbers in [0,1), not in [0,1]. Naturally, the probability of getting 1 is 0 anyway, so this has little practical use, but I'm curious.

Edit: It's pointed out below that the probability of getting 1 would not be 0. So I guess this is a practical question.

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

Replies are listed 'Best First'.
Re: inclusive rand
by LanX (Bishop) on Mar 13, 2017 at 12:40 UTC
> Naturally, the probability of getting 1 is 0 anyway, so this has little practical use, but I'm curious.

But that's exactly the point, because in practical use you want an "integer resolution". (don't know how to phrase it better, look at the examples)

This will produce all values between 0 and 10 inclusively perl -E"say int rand(11) for 1..20"

and this will produce them between 0 and 1 inclusively in 0.1 steps

C:\Windows\system32>perl -E"say 0.1 * int rand(11) for 1..20"

just improve the resolution if 0.1 is not enough, like in

C:\Windows\system32>perl -E"say 1e-6 * int rand(1e6+1) for 1..20"

##### edit

or with full abstraction

perl -E" \$res=1e6; say 1/\$res * int rand(\$res+1) for 1..20"

Please keep in mind that this is not cheating because in perl floats don't have anything like an infinite resolution.

That's why the probability is not 0 like you thought.

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

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

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

Personally I'd make sure to stay below the precision of rand, to avoid skewing the probabilities because of the multiple operations (multiplication, rounding, division) and the error they may imply. Besides, there's nothing particularily significant about the precision of rand, it's probably around the best possible precision on a float. And you could actually get a better resolution than rand with Crypt::Random.

You were clear and you are wrong to believe computer can produce any real numbers. (see also my update)

We can only approximate them with floats, e.g. you will never get a the real pi, just because for instance nobody can ever finish printing a number with an infinite amount of digits.

This means you can only operate on rational numbers with a chosen resolution.

##### update

OP changed text of Re^2: inclusive rand . I'm giving up.

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

> 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!

Re: inclusive rand
by Eily (Parson) on Mar 13, 2017 at 12:46 UTC

Here is one way to do it:

```my \$precision = 8;
for (0..20)
{
my \$var = int(rand(\$precision));
print \$var/(\$precision-1), "\n";
}
Even if the output of rand is not an int, it still is one value among a list of possible ones. Here that fact is explicit rather than implicit, and you get to chose the size of that list.

Maybe Crypt::Random would be a better fit, since you provide a length in bits for the random number, you just have to map 0 to 0, and ~0 to 1 (ie, divide the big unsigned int by the max value).

Thanks. I guess your code would work if I knew what precision rand uses: I could then use that as \$precision.

The other idea looks worth looking into; thanks much.

\$_="msh210";\$"=\$\;@_=@{[split//,uc]}[2,0];\$_="@_\$\1";\$\=\$/;++\$_[0]for\$...1;print lc substr crypt(\$_,"@_"),1,6
Re: inclusive rand
by BrowserUk (Pope) on Mar 13, 2017 at 13:48 UTC

If you multiply rand by 101, int it, then divide by 100, you'll get all possible (2-decimal place) values between 0 and 1 inclusive with 'equal probability':

If you need 3 decimal places, use 1000*int( rand *1001 ); and for 4: 10000*int( rand * 10001 ) etc. Corrected. Thanks to pryrt.

If you need 3 decimal places, use int( rand *1001 )/1000; and for 4: int( rand * 10001 )/10000 etc.

(But beware the number of bits available in the rand() you use. On Windows, pre-5.20something, perl's rand() only has 15-bits. )

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.

"... use 1000*int( rand *1001 ); and for 4: 10000*int( rand * 10001 ) etc." doesn't match the first paragraph, where you multiply by the bigger and divide by the smaller; here, you multiplied twice. I believe it should be, "... use int( rand *1001 )/1000; and for 4: int( rand * 10001 )/10000 etc."?

Tested code rules over untestable text every time :) I'll correct it. Thanks.

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.

Thanks. That's roughly what others have answered.

\$_="msh210";\$"=\$\;@_=@{[split//,uc]}[2,0];\$_="@_\$\1";\$\=\$/;++\$_[0]for\$...1;print lc substr crypt(\$_,"@_"),1,6
Re: inclusive rand
by Discipulus (Monsignor) on Mar 13, 2017 at 12:37 UTC
hello msh210

beside rand and srand Math::Random::MTwist can be of your interest.

Also Re: rand() function on Windows systems can be an interesting read.

PS also note that int(rand(2)) return an integer from 0 to 1

PPS ok i misunderstood your question; marioroy offered a valid option

L*

There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

Thanks, but none of the pages you link to seem to discuss my question at all.

\$_="msh210";\$"=\$\;@_=@{[split//,uc]}[2,0];\$_="@_\$\1";\$\=\$/;++\$_[0]for\$...1;print lc substr crypt(\$_,"@_"),1,6
Re: inclusive rand
by vrk (Chaplain) on Mar 13, 2017 at 17:09 UTC

A bit of probability theory: if X has the Uniform(0,1) distribution, the support (range) is [0,1]. If the support is actually [0,1), then the distribution is actually Uniform(0, 1-epsilon) for some small epsilon. In this case, if you knew what epsilon is, you could scale by the width of the support to get Y = X/(1 - epsilon - 0) = X/(1 - epsilon) and Y would have true Uniform(0,1) distribution.

As others have pointed out, there are a number of factors involved and epsilon likely isn't just the machine epsilon or unit roundoff. Besides, even if it were, see pryrt's reply Re^6: inclusive rand. The figure in question is too small; on normal floating point hardware, dividing by 1-epsilon would be no different from dividing by 1.

This finds the smallest difference between any two random values.

```use strict;
use warnings;
use List::MoreUtils qw(uniq);
use List::Util qw(min);

my @samples = sort { \$a <=> \$b } uniq map {rand} 1..3000;

print scalar @samples, " unique samples.\n";

print "The minimum difference is ", min map { \$samples[\$_] - \$samples[
+\$_-1] } 1..\$#samples;

__END__
2861 unique samples.
The minimum difference is 3.0517578125e-005
Re: inclusive rand
by marioroy (Priest) on Mar 13, 2017 at 12:46 UTC

rand also supports something like that. I asked about numbers between 0 and 1. But thanks.

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

Unfortunately, Math::Random::Secure's dependencies have many sub-dependencies.

```use strict;
use warnings;

use Math::Random::Secure 'irand';

# Random number between 0 and 1 inclusive (total 524288-1 numbers).

sub custom_rand {
irand(524288) / 524287;
}

printf("%f\n", custom_rand()) for 1 .. 20;

Regards, Mario.

Edit: Applied correction. Thanks pryrt.

Math::Random::Secure's irand function supports integer between x and y inclusive. Ah yes, that will not work for 0 and 1.

Create A New User
Node Status?
node history
Node Type: perlquestion [id://1184397]
Front-paged by Corion
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (1)
As of 2018-02-25 11:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
When it is dark outside I am happiest to see ...

Results (312 votes). Check out past polls.

Notices?