Velocity Reviews > Random string of digits?

# Random string of digits?

Roy Smith
Guest
Posts: n/a

 12-25-2011
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?

Steven D'Aprano
Guest
Posts: n/a

 12-25-2011
On Sun, 25 Dec 2011 08:30:46 -0500, Roy Smith 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?

'%20d' % random.randint(0, 10**20-1)

--
Steven

Chris Angelico
Guest
Posts: n/a

 12-25-2011
On Mon, Dec 26, 2011 at 12:30 AM, Roy Smith <(E-Mail Removed)> 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).

ChrisA

Chris Angelico
Guest
Posts: n/a

 12-25-2011
On Mon, Dec 26, 2011 at 12:50 AM, Chris Angelico <(E-Mail Removed)> wrote:
> The Python 2 docs [1]

Python 2: http://docs.python.org/library/random.html
And same in Python 3: http://docs.python.org/py3k/library/random.html

ChrisA

Chris Angelico
Guest
Posts: n/a

 12-25-2011
On Mon, Dec 26, 2011 at 12:48 AM, Steven D'Aprano
<(E-Mail Removed)> wrote:
> On Sun, 25 Dec 2011 08:30:46 -0500, Roy Smith 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?

>
> '%20d' % random.randint(0, 10**20-1)

I should mention that this sort of thing is absolutely acceptable in
situations where you don't actually need that level of randomness; if
you want to assign 20-digit numbers to each of ten million objects,
you can happily use something that's only really random to fifteen. I
use this technique with base 36 numbers to generate arbitrary
alphanumeric strings to use as message tags, for instance; fill out a
specified field size, even though not every combination will actually
be used.

ChrisA

Roy Smith
Guest
Posts: n/a

 12-25-2011
In article <(E-Mail Removed)>,
Chris Angelico <(E-Mail Removed)> wrote:

> "%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).

Actually, the only entropy involved here is the ever increasing amount
of it between my ears. It never occurred to me to try that

> 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).

Hmmm. In my case, I was looking more to optimize clarity of code, not
speed. This is being used during account creation on a web site, so it
doesn't get run very often.

It turns out, I don't really need 20 digits. If I can count on

>>> "%020d" % random.randint(0,999999999999999)

to give me 15-ish digits, that's good enough for my needs and I'll
probably go with that. Thanks.

Chris Angelico
Guest
Posts: n/a

 12-25-2011
On Mon, Dec 26, 2011 at 1:21 AM, Roy Smith <(E-Mail Removed)> wrote:
> It turns out, I don't really need 20 digits. *If I can count on
>
>>>> "%020d" % random.randint(0,999999999999999)

>
> to give me 15-ish digits, that's good enough for my needs and I'll
> probably go with that. *Thanks.

I'd say you can. The information about the Mersenne Twister underlying
the module's functions isn't marked as "CPython Implementation Note",
so I would expect that every Python implementation will provide a
minimum of 53-bit precision. (It does have the feeling of an
implementation detail though; is there a guarantee that two Pythons
will generate the same sequence of numbers from the same seed?)

ChrisA

Peter Otten
Guest
Posts: n/a

 12-25-2011
Chris Angelico wrote:

> On Mon, Dec 26, 2011 at 12:30 AM, Roy Smith <(E-Mail Removed)> 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:

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})

Steven D'Aprano
Guest
Posts: n/a

 12-25-2011
On Mon, 26 Dec 2011 01:51:30 +1100, Chris Angelico wrote:

> On Mon, Dec 26, 2011 at 1:21 AM, Roy Smith <(E-Mail Removed)> wrote:
>> It turns out, I don't really need 20 digits. Â*If I can count on
>>
>>>>> "%020d" % random.randint(0,999999999999999)

>>
>> to give me 15-ish digits, that's good enough for my needs and I'll
>> probably go with that. Â*Thanks.

>
> I'd say you can. The information about the Mersenne Twister underlying
> the module's functions isn't marked as "CPython Implementation Note", so
> I would expect that every Python implementation will provide a minimum
> of 53-bit precision. (It does have the feeling of an implementation
> detail though; is there a guarantee that two Pythons will generate the
> same sequence of numbers from the same seed?)

Yes.

http://docs.python.org/dev/library/r...eproducibility

I think that's a new guarantee. Previously, the answer was only yes-ish:
in theory, no guarantee was made, but in practice, you could normally
rely on it. For example, when the Mersenne Twister became the default
random number generator, the old generator, Wichman-Hill, was moved into
its own module whrandom (deprecated in 2.4; now gone) for those who
needed backwards compatibility.

--
Steven

Steven D'Aprano
Guest
Posts: n/a

 12-25-2011
On Mon, 26 Dec 2011 00:54:40 +1100, Chris Angelico wrote:

> On Mon, Dec 26, 2011 at 12:48 AM, Steven D'Aprano
> <(E-Mail Removed)> wrote:
>> On Sun, 25 Dec 2011 08:30:46 -0500, Roy Smith 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?

>>
>> '%20d' % random.randint(0, 10**20-1)

>
> I should mention that this sort of thing is absolutely acceptable in
> situations where you don't actually need that level of randomness;

Use the Source, Luke, er, Chris

If I've read the source correctly, randint() will generate sufficient
bits of randomness to ensure that the entire int is random.

http://hg.python.org/cpython/file/default/Lib/random.py

--
Steven

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is OffTrackbacks are On Pingbacks are On Refbacks are Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post VK Javascript 15 05-02-2010 03:43 PM globalrev Python 4 04-20-2008 08:12 AM Lars-Erik Aabech ASP .Net 8 04-28-2005 07:52 AM Maziar Aflatoun ASP .Net 4 08-05-2004 01:26 AM Darren Clark ASP .Net 3 06-24-2004 05:23 PM