Chris Angelico wrote: > On Mon, Dec 26, 2011 at 12:30 AM, Roy Smith <r...@panix.com> wrote: >> I want to create a string of 20 random digits (I'm OK with leading >> zeros). The best I came up with is: >> >> ''.join(str(random.randint(0, 9)) for i in range(20)) >> >> Is there something better? > > The simple option is: > random.randint(0,99999999999999999999) > or > "%020d"%random.randint(0,99999999999999999999) > (the latter gives you a string, padded with leading zeroes). But I'm > assuming that you discarded that option due to lack of entropy (ie you > can't trust randint() over that huge a range). > > The way I'd do it would be in chunks. The simple option is one chunk; > your original technique is twenty. We can go somewhere in between. > First thing to do though: ascertain how far randint() is properly > random. The Python 2 docs [1] say that the underlying random() > function uses 53-bit floats, so you can probably rely on about that > much randomness; for argument's sake, let's say it's safe for up to > 10,000 but no further (although 53 bits give you about 15 decimal > digits). > > ''.join('%04d'%random.randint(0,9999) for i in range(5)) > > For your actual task, I'd be inclined to take ten digits, twice, and > not bother with join(): > > '%010d%010d'%(random.randint(0,9999999999),random.randint(0,9999999999)) > > Looks a little ugly, but it works! And only two random number calls > (which can be expensive).
Judging from a quick look into the code (method Random._randbelow()) I'd say you don't need to do that unless you override Random.random() and not Random.getrandbits(). Even if you roll your own random() you'll get a warning when you run into the limit: >>> import random >>> random.randrange(10**20) 27709407700486201379L >>> class R(random.Random): ... def random(self): return 4 # * ... >>> R().randrange(10**20) /usr/lib/python2.6/random.py:253: UserWarning: Underlying random() generator does not supply enough bits to choose from a population range this large _warn("Underlying random() generator does not supply \n" 400000000000000000000L (*) According to the literature 4 is the best random number, 9 being the runner-up: http://www.googlefight.com/index.php?lang=en_GB&word1=random+number+dilbert&word2=random+number+xkcd A quick sanity check: >>> from collections import Counter >>> import random >>> Counter(str(random.randrange(10**10000))) Counter({'9': 1060, '6': 1039, '3': 1036, '8': 1007, '7': 997, '4': 977, '1': 976, '5': 976, '2': 970, '0': 962}) -- http://mail.python.org/mailman/listinfo/python-list