May 26, 2023
Inspired by a comment on HN, the difference between random() * random()
and random() ** 2
.
from random import random
from collections import Counter
import matplotlib.pyplot as plt
import numpy as np
def generate_count(f, iter, precision):
counter = Counter()
for i in range(iter):
counter[int(f() * precision) / precision] += 1
return counter
random_random = generate_count(lambda: random() * random(), 1000000, 100000)
data = np.array(sorted(random_random.items()))
x, y = data.T
plt.scatter(x,y)
plt.show()
random_squared = generate_count(lambda: random() ** 2, 1000000, 100000)
data = np.array(sorted(random_squared.items()))
x, y = data.T
plt.scatter(x,y)
plt.show()
Looks like random() ** 2
clearly has much smaller values. Here's my (maybe wrong) intuition. Consider the $x\in[0,1],y\in [0,1]$ square. Think of random() * random()
drawing uniformly within the 1 by 1 square, and mulitplying the $x$ and $y$ value. Then, random() ** 2
is like the diagonal line, where $x = y$. It makes sense that small values are a larger part of of the diagonal line than the square. Say $x,y \leq 0.1$ produces a value of $xy = 0$ after the precision cutoff. Then $P(xy = 0) = 0.1$ for the line, but $P(xy = 0) = 0.1^2$ for the square produces $0$.