Random string of digits?
Peter Otten
__peter__ at web.de
Sun Dec 25 10:21:49 EST 2011
Chris Angelico wrote:
> On Mon, Dec 26, 2011 at 12:30 AM, Roy Smith <roy at 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})
More information about the Python-list
mailing list