Reputation: 5800
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
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
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')
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')
This way, you are sure to have a regular distribution of a 16 digit numbers.
Upvotes: 5
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