Come generare numeri casuali in Python

I numeri casuali sono fondamentali in molte aree della programmazione e della scienza. Python offre diversi modi per generare numeri pseudo-casuali per una varietà di scopi.

In questa guida completa spiegheremo cosa sono e come generare numeri casuali in Python.

Cos’è un numero casuale

Un numero casuale è un valore generato da un processo tale che non ci sono regolarità o modelli che possano essere sfruttati per prevedere il prossimo numero.

I numeri veramente casuali sono impossibili da generare con un computer, perché i computer sono intrinsecamente deterministici. Tuttavia, ci sono algoritmi che possono simulare l’aleatorietà producendo una sequenza di numeri che appaiono non correlati tra loro. Questi sono chiamati numeri pseudo-casuali.

Le sequenze di numeri pseudo-casuali hanno diverse applicazioni, come ad esempio:

  • Simulazioni ed esperimenti scientifici
  • Giochi d’azzardo
  • Sicurezza informatica e crittografia
  • Campionamento statistico
  • Machine learning

Generatori di numeri casuali in Python

Python offre diversi moduli integrati per generare numeri casuali per varie distribuzioni statistiche. I principali sono:

Random

Il modulo random è il modo più semplice per generare numeri pseudo-casuali in Python. Fornisce funzioni per generare numeri casuali, campionare sequenze casuali e permutare sequenze in modo casuale.

Ecco alcuni esempi di utilizzo di random:

import random

# Generate a random integer between 1 and 10
random_num = random.randint(1,10) 

# Generate a random float between 0 and 1  
random_float = random.random()

# Sample a random element from a list
my_list = [1, 2, 3, 4]  
random_element = random.choice(my_list)

Secrets

Il modulo secrets è stato introdotto in Python 3.6 ed è raccomandato per la generazione di dati crittografici come password o chiavi crittografiche. È progettato per essere più sicuro rispetto a random.

import secrets

# Generate a random integer between 1 and 10
secure_num = secrets.randbelow(10) 

# Generate a random float between 0 and 1
secure_float = secrets.randbits(5) 

# Generate a random token
token = secrets.token_hex(16)

Numpy

Il pacchetto NumPy fornisce generatori di numeri pseudo-casuali avanzati basati su algoritmi come il generatore Mersenne Twister. Questi possono essere utilizzati per creare array di numeri casuali da diverse distribuzioni.

import numpy as np

# Generate a 1-D array containing 5 random ints between 0 and 10  
random_ints = np.random.randint(0,10,5)

# Generate a 2x3 array with random floats between 0 and 1
random_floats = np.random.random((2,3))

# Sample 5 values from a normal distribution with mean=0 and stddev=1
random_normal = np.random.normal(0, 1, 5)

Impostare il seed

I generatori di numeri casuali in Python sono basati su algoritmi deterministici. Ciò significa che genereranno sempre la stessa sequenza di numeri dato uno specifico seed.

Il seed è il numero iniziale usato per generare la sequenza pseudo-casuale. Impostando lo stesso seed si otterrà la stessa sequenza di “numeri casuali”.

Per impostare il seed si usa il metodo seed() del generatore random:

import random
random.seed(10) 

print(random.random()) # 0.5714025946899135
print(random.random()) # 0.4288890546751146 

random.seed(10)

print(random.random()) # Di nuovo 0.5714025946899135

Ciò è utile per riprodurre esperimenti o quando si vogliono risultati prevedibili durante il test del codice.

In generale, è meglio non impostare il seed e lasciare che venga inizializzato in modo casuale per ogni nuova esecuzione del programma.

Generare numeri casuali da una distribuzione

Oltre a generare numeri casuali uniformi, spesso è necessario generare valori da una specifica distribuzione di probabilità come la normale, binomiale, Poisson, ecc.

I moduli random e numpy forniscono metodi per generare campioni da diverse distribuzioni statistiche comuni.

Ad esempio, per generare una variabile casuale con distribuzione normale:

from random import normalvariate

# Normal distribution with mean=0 and stddev=1
normal_var = normalvariate(0, 1) 

from numpy.random import normal
normal_array = normal(0, 1, 100) # 100 values

Altri esempi di distribuzioni supportate:

  • random.gauss(mu, sigma) – Gaussiana
  • random.betavariate(alpha, beta) – Beta
  • random.expovariate(lambd) – Esponenziale
  • random.paretovariate(alpha) – Pareto
  • random.weibullvariate(alpha, beta) – Weibull
  • numpy.random.binomial – Binomiale
  • numpy.random.poisson – Poisson

Consulta la documentazione di random e numpy.random per l’elenco completo delle distribuzioni supportate.

Simulazioni ed esempi

I numeri casuali sono ampiamente usati per simulare sistemi e processi del mondo reale in diversi campi. Eccone alcuni esempi in Python:

Lancio di dadi

Simuliamo il lancio di due dadi e ne stampiamo il risultato:

import random

for i in range(5):
  print(random.randint(1,6) + random.randint(1,6))

Risultato possibile:

8
10
5
9
7

Cammino casuale

Simuliamo una passeggiata casuale di 100 passi, in cui ad ogni passo ci si può muovere di +1 o -1:

import random

position = 0
walk = [position]

for i in range(100):
step = 1 if random.randint(0, 1) else -1
position += step
walk.append(position)

print(walk)

Simulazione di lancio di monete

Lanciamo una moneta 100 volte e contiamo quante volte esce testa:

python
import random

flips = 0
heads = 0

for i in range(100):
if random.randint(0, 1) == 1:
flips += 1
heads += 1

else:
flips += 1

print(f'Su {flips} lanci, testa è uscita {heads} volte')

Generare numeri random con Python – FAQ

Come evitare bias nei numeri casuali?

Imposta correttamente il seed ad ogni esecuzione per evitare sequenze prevedibili.

Come generare numeri casuali sicuri per scopi crittografici?

Usa il modulo secrets di Python invece di random per generare chiavi e token.

Posso generare numeri veramente casuali in Python?

No, in informatica è possibile solo generare pseudo-randomness. Ma con un buon algoritmo è indistinguibile dalla vera casualità.