MiniGunnR
MiniGunnR

Reputation: 5800

Generating random 16 digit number in Python

str(uuid.uuid4().int>>64)[0:8] + str(uuid.uuid4().int>>64)[0:8]

I want to create a 16 digit random number with the above code. If I generate it in two parts, does it make it more random or can I just do the following:

str(uuid.uuid4().int>>64)[0:16]

Upvotes: 2

Views: 13106

Answers (3)

Jason S
Jason S

Reputation: 13779

The uuid4 implementation in Python tries to use a system-provided uuid generator if available, then os.urandom() (so-called "true" randomness), then random.randrange() (which uses a PRNG) if neither is available. In the first two cases the randomness "should" be about as random as you can ask for from your computer. In the PRNG case each random byte is generated separately, so concatenating two halves really shouldn't help.

We can empirically check how even the distribution of digits is using code like this:

import uuid
digits = [0] * 10
for i in range(100000):
    x = str(uuid.uuid4().int)[-16:]
    for d in x:
        digits[int(d)] += 1
print(digits)

Note that I changed your code, removing >>64 because it can make the number too short and changing the slice to take the last 16 digits instead. The distribution of digits is pretty even.

[159606, 159916, 160188, 160254, 159815, 159680, 159503, 160015, 160572, 160451]

Now, let's see what changing to str(uuid.uuid4().int)[-8:] + str(uuid.uuid4().int)[-8:] does from a distribution standpoint:

[159518, 160205, 159843, 159997, 160493, 160187, 160626, 159665, 159429, 160037]

Basically nothing.

Incidentally, taking from the start of the string without the bit shift:

[151777, 184443, 184347, 166726, 151925, 152038, 152178, 152192, 151873, 152501]

There is bias toward 1s and 2s due to the 6 nonrandom bits at the beginning of the uuid4.

Upvotes: 3

Taha
Taha

Reputation: 778

I invite you to be careful about the random number generator you are using. I made a test of the generated numbers distribution. Here is what I found:

import uuid
import numpy as np
import matplotlib.pyplot as plt

# Generation of 100000 numbers using the [0:8] + [0:8] technique
res1 = np.empty(shape=100000, dtype=int)
for i in xrange(res1.size):
    tmp = str(uuid.uuid4().int>>64)[0:8] + str(uuid.uuid4().int>>64)[0:8]
    res1[i] = int(tmp)

# Generation of 100000 numbers using the [0:16] technique
res2 = np.empty(shape=100000, dtype=int)
for i in xrange(res1.size):
    tmp = str(uuid.uuid4().int>>64)[0:16]
    res2[i] = int(tmp)

# Histogram plot
plt.setp(patches, 'facecolor', 'g', 'alpha', 0.75)
n, bins, patches = plt.hist(res1, 100, normed=1, histtype='stepfilled')
n, bins, patches = plt.hist(res2, 100, normed=1, histtype='stepfilled')

Generation of random numbers as proposed in the question

As we notice, the methods are the same. Nevertheless, the second one [0:16] can give 0 as a first digit, which make 15 digit numbers.

Why do not you use the function random.

# Generation of random numbers using `random` function
res3 = np.random.randint(1e15, 1e16, 100000)
# Plot
n, bins, patches = plt.hist(res3, 100, normed=1, histtype='stepfilled', label='randint')

Generation of random numbers with the function randint

This way, you are sure to have a regular distribution of a 16 digit numbers.

Upvotes: 5

MariusSiuram
MariusSiuram

Reputation: 3644

Looking at only your title, I should ask, why not:

from random import randint
s = ''
for i in range(16):
    s = s + str(randint(0,9))

You have not explained the reason to use UUID, and to me, it seems quite odd.

Upvotes: 1

Related Questions