lmacken / quantumrandom

Tools for utilizing the ANU Quantum Random Number Generator
https://pypi.python.org/pypi/quantumrandom
146 stars 36 forks source link

Range Problem #16

Open whoisstan opened 9 years ago

whoisstan commented 9 years ago

hi, i was looking at the library and i think there is a problem with min/max, as I understand it loops, gets a new number and checks if this outside of the range. i think this has a tendency towards large numbers. i think this is the better solution: http://stackoverflow.com/a/28750276/238847 best, stan

lmacken commented 9 years ago

Hi there, thanks for the report.

I actually didn't write that function, but one of the folks that works on the ANU quantum random number generator sent me this email about the previous version a while ago.

I had a look at the randint() function. It will return a number that  
is not uniform between min and max unless max-min+1 is exactly        
divisible by 65536. It will be off by a small factor.                 
http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Modulo_bias 

Here's our php code that returns a number between (0--$max)           
function qrand ($max)                                                 
{                                                                     
  $range=$max+1;                                                      
  $too_big_range = (int)(65536/$range) * $range; # integer division   
(returns integer)                                                     

  do {                                                                
    $day = unpack('S', fread(fopen('/var/local/qrandom', 'r'),2)); #  
'S' = 2bytes = 16 bit                                                 
    if ( $day[1] >= $too_big_range ){                                 
  }                                                                   
  else{                                                               
  return ($day[1] % $range);                                          
  }                                                                   
}while (1);                                                           

}                                                                     

@ralphbean then updated it in pull #7 in an effort to resolve this bias. So, there still may be bugs, but the technique itself was recommended by the creators of the qrng.

adamcw commented 8 years ago

This bug has not been resolved in Python 3.

modulos = source_max / rand_range
too_big = modulos * rand_range

This code relies on the default division of these two numbers being integer division, which is true in Python 2 but not in Python 3.

Changing this code to:

modulos = source_max // rand_range
too_big = modulos * rand_range

Would fix the issue. Also commenting that this is explictly intended to be integer division would make it clearer that too_big doesn't always simply equal source_max.