# random number including 1 - i.e. [0,1]

Dave Angel davea at ieee.org
Wed Jun 10 07:58:52 CEST 2009

Steven D'Aprano wrote:
> On Tue, 09 Jun 2009 18:28:23 -0700, John Yeung wrote:
>
>
>> The docs are now... sort of correct.  For some values of a and b,
>> uniform() can never return b.  Notably, I believe uniform(0, 1) is
>> equivalent to random(), and will never return 1.  However, uniform(1, 2)
>> CAN return 2, if this is any indication:
>>
>>
>>
>>>>> a=0.0
>>>>> b=1.0
>>>>> a+(b-a)*z < b
>>>>>
>> True
>>
>>>>> a=1.0
>>>>> b=2.0
>>>>> a+(b-a)*z < b
>>>>>
>> False
>>
>
>
> But you haven't shown what value z has, so there's no way of interpreting
> that example.
>
> I'd say that uniform(1, 2) should NOT return 2, at least for systems
> which round correctly. Given a random z such that:
>
> 0 <= z < 1
>
> and two floats a, b such that:
>
> a < b
>
> (b is strictly the larger of the two) then:
>
> 0 <= z < 1
>
> Multiply all sides by (b-a):
>     0 <= (b-a)*z < (b-a)
>
> Add a to all sides:
>     a <= a + (b-a)*z < b
>
>
> Hence uniform(a, b) should always return a result less than b, and
> greater or equal to a.
>
> However, there is one proviso: floats are not reals. The above holds true
> for real numbers, but floats are subject to weird rounding effects. That
> means that there may be weird edge cases where Bad Things happen and
> things cancel catastrophically or round incorrectly.
>
> A realistic edge case is that a + (b-a) doesn't always give b:
>
>
>>>> a = -1e90
>>>> b = 1.0
>>>> a < b
>>>>
> True
>
>>>> a + (b-a) == b
>>>>
> False
>
>>>> a + (b-a)
>>>>
> 0.0
>
>
> However, even in this case, it merely narrows the range of possible
> results, it doesn't widen it.
>
>
>
Did you try to find the edge case for z ?  For the following, I'm using
Python 2.6.2, running on XP, on a Pentium Core Duo.

I figure the highest theoretical value that random.random() should
return is a number just under 1.0   The easiest way to generate that
value is using the fromhex() method of float.

>>> z =      float.fromhex("0x1.fffffffffffffp-1")
>>> z
0.99999999999999989
>>> z<1.0
True
>>> z2 = 1.0 + z
>>> z2
2.0
>>> z2 < 2.0
False