Python PR

【Python】randomモジュールを使った乱数の使い方を解説

記事内に商品プロモーションを含む場合があります

この記事では、Pythonで擬似乱数を生成する方法を解説します。

Pythonで乱数を扱うには、標準ライブラリのrandomモジュールを使います。乱数を使うことでジャンケンなどのちょっとした遊びも実装できます。

それでは、乱数の使い方を見ていきましょう!

randomモジュール

Pythonで乱数を扱うには、randomモジュールを使います。標準ライブラリなのでインポートするだけで使用可能です。

import random

randomモジュールには、乱数を生成するための様々な関数が定義されています。

Linkrandom --- 擬似乱数を生成する — Python ドキュメント

中でもよく使用される関数の使い方を見ていきましょう!

ランダムな整数を生成する

ランダムな整数を生成するには、以下の関数を使います。

randrange range(start, stop, step)の要素から、1つランダムに選んで返します。
randint randrange(a, b+1) のエイリアス
getrandbits k個のビット数の範囲から、1つランダムに選んで返します。

任意の範囲の整数からランダムに1つ取得

randrange()関数は、range()関数と同じ引数を取り、同様な範囲を生成します。そして、生成した範囲の中からランダムに要素を1つ取得します。

randrange(start,stop,step)

range()関数で生成した範囲とrandrange()関数で取得した値を見比べています。

import random

print(f'range: {list(range(5))}, value: {random.randrange(5)}')
print(f'range: {list(range(3, 8))}, value: {random.randrange(3, 8)}')
print(f'range: {list(range(1, 10, 2))}, value: {random.randrange(1, 10, 2)}')

実行結果

range: [0, 1, 2, 3, 4], value: 1
range: [3, 4, 5, 6, 7], value: 7
range: [1, 3, 5, 7, 9], value: 5

step引数を指定しない場合は、randint()関数を使う方が簡単です。randint()関数は、randrange(a, b+1)のエイリアスです。

randint(a, b)

randrange()関数とは異なり、a < N <= bなことに注意しましょう。

import random

print(f'range: {list(range(1, 5+1))}, value: {random.randint(1, 5)}')

実行結果

range: [1, 2, 3, 4, 5], value: 5​

任意のビット数からランダムに整数を1つ取得

指定したビット数で生成される整数の中から1つ取得するには、getrandbits()関数を使います。

getrandbits(k)

k個のビット数の範囲から生成される整数からランダムに1つ返します。

import random

# 0000 ~ 0011
print(random.getrandbits(2))

# 0000 ~ 1111
print(random.getrandbits(4))

実行結果

3
14

ランダムな実数を生成する

ランダムな実数を生成するには、以下の関数を使います。

random() 「0.0 ~ 1.0」の範囲からランダムに実数を返します
uniform(a, b) 「a ~ b」の範囲内の実数をランダムに返します

0.0~1.0の範囲の実数をランダムに取得

「0.0 ~ 1.0」の範囲からランダムに実数を返します。

import random

print(random.random())

実行結果

0.8743999006747728

桁数が大きすぎる場合は round()関数 を使って小数を丸める。

import random

print(round(random.random(), 2))

実行結果

0.27
【Python】小数の切り上げ・切り捨て・四捨五入Python で小数点を切り上げ、切り捨て、四捨五入する方法を解説します。値が正確じゃなくていいなら round関数 を使い、正確に取得したい場合は Decimalクラス を使うという感じでいいと思います。...

任意の範囲の実数をランダムに取得

任意の範囲の実数を1つランダムに取得するには uniform()関数 を使います。

uniform(a, b)

a ~ b の範囲内の実数をランダムに返します。a と b どちらが大きくても問題ありません。

import random

# uniform(2, 1)でも同じ
print(random.uniform(1, 2))

# 桁数が大きい場合はround関数を使う
print(round(random.uniform(1, 2), 2))

実行結果

1.3158320605493328
1.85

ランダムなバイト列を生成する

ランダムなバイト列を生成するには、randbytes()関数を使います。この関数は、Python 3.9で追加されました。

randbytes(n)

nバイトのバイト列がランダムに生成されます。

import random

for i in range(1, 6):
    print(f'{i}: {random.randbytes(i)}')

実行結果

1: b'\xf5'
2: b'\x04\xec'
3: b'\x1b\x04Z'
4: b'\xe0\xff\x9b\x9a'
5: b'He\x93\x10\x7f'

シーケンスの要素をランダムに取得する

整数や実数以外のオブジェクトをランダムに取得するには、シーケンスに格納された要素をランダムに取得することで実現できます。

要素をランダムに取得する

シーケンスの要素をランダムに取得するには、random.choise()関数を使います。

random.choice(seq)

choice()関数は、引数に指定されたシーケンスの要素をランダムに返します。引数に指定したシーケンスが空の場合はIndexErrorが発生します。

import random

l = [1, 2, 3, 4, 5]

for i in range(3):
    print(random.choice(l))

# 要素を抜き取っているわけではないので重複もあり得る
print(l)

実行結果

3
1
4
[1, 2, 3, 4, 5]

確率を変更して要素を取得する

確率を変更してシーケンスの要素をランダムに取得したい場合は、random.choises()関数を使います。

random.choices(population, weights=None, *, cum_weights=None, k=1)

population引数に指定したシーケンスからk個の要素をランダムに取得します。

また、重みを渡すことで要素が選ばれる確率を変更することができます。重みはweights引数、またはcum_weights引数にシーケンスを渡すことで指定できます。重みが渡されなかった場合は同じ確率で選択されます。

import random

# ガチャの中身
contents = ('超激レア', '激レア', 'レア')

# 累積的な重み(超激レア=10%, 激レア=20%, レア=70%)
cum_weights = (1, 3, 10)

# 10連ガチャ(k引数で回数を指定しています)
gacha10 = random.choices(contents, cum_weights=cum_weights, k=10)
print(gacha10)

実行結果

['レア', 'レア', '激レア', 'レア', '超激レア', '激レア', '激レア', 'レア', 'レア', 'レア']
  • 重みの長さはpopulationに指定したシーケンスと同じにする
  • 相対的な重みは関数内で累積的な重みに変換されるので、最初から累積的な重みを渡すほうが効率が良い

重みの補足

重みには「相対的な重み」と「累積的な重み」があります。どのように指定すればいいのか、もう少しだけ詳しく見ていきましょう!

相対的な重み

相対的な重みで「10%」「30%」「60%」の確率で要素を取得するには、以下のように指定します。

weights = (10, 30, 60)

確率は「要素の値 / 合計値」で計算されます。上記シーケンスの合計は100なので、10 / 100 = 0.130 / 100 = 0.360 / 100 = 0.6となっています。

なので、以下のような重みは先ほどの重みと同等です。

# 合計 50
weights = (5, 15, 30)
# 合計 10
weights = (1, 3, 6)
累積的な重み

累積的な重みで「10%」「30%」「60%」の確率で要素を取得するには、以下のように指定します。

cum_weights = (1, 4, 10)

確率は「左の要素から増えた値 / 末尾の要素の値」で計算されます。上記シーケンスの末尾の値は10なので、(1 - 0) / 10 = 0.1(4 - 1) / 10 = 0.3(10 - 4) / 10 = 0.6となっている。

なので、以下のような重みは先ほどの重みと同等である。

cum_weights = (5, 20, 50)
cum_weights = (10, 40, 100)

シーケンスの要素をランダムに並び替える

シーケンスの要素をランダムに並び替えるには、shuffle()関数を使います。並び替えたシーケンスを返すのではなく、引数に指定されたシーケンスを並び変えます。

import random

# 連番のリスト生成
nums = list(range(1, 6))
print(nums)

# シャッフル
random.shuffle(nums)
print(nums)

実行結果

[1, 2, 3, 4, 5]
[1, 4, 2, 5, 3]

まとめ

この記事では、Pythonの乱数の使い方を簡単に解説しました。

乱数を使うことで何かしら値が必要な時にランダムに値を生成することができます。

randomモジュールには、今回紹介したもの以外にたくさんの関数が定義されています。気になる方は、公式ドキュメントを参照してください。

重複しない乱数を生成するには以下の記事を参照してください。

重複しない乱数の生成方法

それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ

【Python】ジャンケンを実装してみよう【サンプルプログラム】この記事では、Pythonの練習としてジャンケンを実装してみます。ジャンケンは、if文 や while文、乱数などを組み合わせることで実装できます。また、マジックナンバーを使わないように 列挙型 を使って定義することもできます。それでは、ジャンケンを作っていきましょう!...