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





More information about the Python-list mailing list