So, as I understand it, random.random() returns a number 0<n<1 where n is a real number of type float. Then, random.randint(x,y) returns a number x<=n<=y where n is an integer value and x, y are user defined limits. random.random() creates distributions, and I would think it returns real numbers in normal distributions (by which I mean distributions of equal mean, median and mode so equal probability). I can’t find information on how random.randint(x,y) works though. I would have thought it was very similar under the hood, but that doesn’t explain why it seems to work differently. When I try and do a web search, I just get pages and pages of information on how to code it syntax-wise, not how it works. That’s Google’s algorithms for you, unfortunately.

The reason I am asking is because the difference between these two functions tripped me up on the probability calculator, and I am not entirely comfortable proceeding until I understand why. It’s one thing to say “this is the output”, but if you don’t know why, you can’t use the functions properly. Would really appreciate any help here, a link to further information or something.

Take the size of the range. It’s inclusive on both sides so the size of (50, 60) is 11.

Generate enough random bits to represent all values from 0 through size. If the resulting binary number is larger than size, repeat.

Take this random integer and add it to the start of the original range.

random.choice works the same way except over a range of indices. In CPython, everything except the random bit generation happens in python. The ultimte source of the randomness is hardware/OS dependent but is supposed to be close to uniform.

random() creates distributions, and I would think it returns real numbers in normal distributions (by which I mean distributions of equal mean, median and mode so equal probability).

random.random and and random.randint both have a uniform distribution. Maybe you mean symmetrical but normal is definitely wrong

The reason I am asking is because the difference between these two functions tripped me up on the probability calculator, and I am not entirely comfortable proceeding until I understand why.

If I understand correctly, you tried to multiply random.random() and then truncate it so you could use it as an index. That’s not very readable but the result should be close enough. And it is close enough if you increase the number of iterations. The problem here is the test. It wants something within 0.01 of 0.272 but the actual probability is 0.2636. This effectively means you’re expected to do it in a particular way that has nothing to do with correctness.

I think most of this is a practical issue. The project uses a seed for the random number generation to provide reproducibility and with 1000 trials the result was 0.272 (regardless of the actual probability). So the choice is to have a tight tolerance and use a certain set of methods that are designed for python iterables or a looser tolerance to include more methods. As it stands, the 0.272 +/- 0.01 includes the actual probability. This has been discussed before, I believe, and there was really no consensus on changing the tolerances or increasing the iterations. So that really punts the question to why the methods are different.

The iterable friendly methods, i.e. choices, randrange (which includes randint), etc. are designed to produce a uniform distribution of random integers (documentation). You’ll note in the documentation that there is a warning that int(random.random() * n) can produce uneven distributions which I assume is due to the differences in representation of floats and integers and their distribution on various ranges (integers can be represented exactly in binary while only certain real numbers can be represented exactly as floats). random.random()'s open interval also means there will be fewer numbers generated on the top end (admittedly it’s only one out of infinity on paper, but the floating point representation of the top of the interval could change that ratio). There’s a world of computer science in random number generation that could be studied to answer this question.

Regardless, combined with the documentation, I think this project serves as a useful introduction to handling random number generation with care.