Pythonのrandom関数で乱数を生成する15の方法

Pythonでrandom関数を使って乱数生成する方法Python
この記事は約19分で読めます。

※本記事のコンテンツは、利用目的を問わずご活用いただけます。実務経験10000時間以上のエンジニアが監修しており、基礎知識があれば初心者にも理解していただけるように、常に解説内容のわかりやすさや記事の品質に注力しております。不具合・分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。(理解できない部分などの個別相談も無償で承っております)
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)


●randomモジュールとは

ゲームやシミュレーションを作る上で、乱数は欠かせない存在です。

そんな乱数を生成するためのPythonのモジュールが「random」です。

randomモジュールを使えば、整数や小数、文字列などの乱数を簡単に生成できちゃうんです。

しかも、ただ乱数を生成するだけじゃありません。

重複のない乱数を生成したり、特定の範囲内で乱数を生成したりと、様々なニーズに応えてくれます。

○randomモジュールのインポート方法

randomモジュールを使うためには、まずはモジュールをインポートする必要があります。

モジュールのインポートは、とても簡単ですよ。

○サンプルコード1:randomモジュールのインポート

import random

たったこれだけで、randomモジュールがインポートされます。

これで、乱数生成の準備は完了です。

●整数の乱数生成

さて、randomモジュールのインポート方法がわかったところで、早速整数の乱数を生成してみましょう。

整数の乱数生成は、サイコロを振るようなものだと思ってください。

1から6までの数字がランダムに出るように、プログラムでも指定した範囲内の整数をランダムに生成できるんです。

○サンプルコード2:1〜10までの整数の乱数生成

それでは、1から10までの整数をランダムに生成するコードを見てみましょう。

import random

random_number = random.randint(1, 10)
print(random_number)

実行結果

7

random.randint(1, 10)という部分で、1から10までの整数をランダムに生成しています。

この関数は、指定した範囲の両端の値(この場合は1と10)を含むのがポイントです。

生成された乱数は、random_number変数に代入されて、print関数で出力されています。

実行するたびに、1から10までの整数がランダムに表示されるはずです。面白いですよね。

○サンプルコード3:特定の範囲内の整数の乱数生成

1から10までじゃなくて、もっと広い範囲で乱数を生成したいこともあるでしょう。

そんなときは、random.randint()関数の引数を変えるだけです。

import random

random_number = random.randint(1, 100)
print(random_number)

実行結果

42

random.randint(1, 100)とすることで、1から100までの範囲で整数の乱数を生成できました。

とても簡単ですね。

○サンプルコード4:複数の整数の乱数生成

1つの乱数だけじゃなくて、複数の乱数を一度に生成したいこともあるでしょう。

そんなときは、for文を使って繰り返し処理を行います。

import random

for _ in range(5):
    random_number = random.randint(1, 100)
    print(random_number)

実行結果

78
23
91
6
54

for _ in range(5)という部分で、5回の繰り返し処理を行っています。

_(アンダースコア)は、変数を使わないことを示しています。

繰り返しの中で、random.randint(1, 100)を使って1から100までの整数の乱数を生成し、print関数で出力しています。

実行結果を見ると、5つの乱数が生成されていることがわかります。

●浮動小数点数の乱数生成

整数の乱数に続いて、今度は浮動小数点数の乱数を生成してみましょう。

浮動小数点数っていうと、ちょっと難しそうに聞こえますが、要は小数点以下の数字も含めた数値のことです。

乱数の世界では、整数だけでなく小数も大活躍。

例えば、確率計算やシミュレーションなどで使われることが多いんです。

小数点以下の細かい値をランダムに生成できれば、より現実に近い結果が得られるかもしれません。

それじゃあ、実際にコードを見ながら、浮動小数点数の乱数生成に挑戦してみましょう。

○サンプルコード5:0〜1までの浮動小数点数の乱数生成

まずは、0から1までの範囲で浮動小数点数の乱数を生成するコードから始めます。

import random

random_float = random.random()
print(random_float)

実行結果

0.7564186024489547

random.random()という関数を使うと、0以上1未満の浮動小数点数がランダムに生成されます。

生成された乱数は、random_float変数に代入されて、print関数で出力されています。

実行結果を見ると、0.7564186024489547のような小数点以下の長い数字が表示されていますね。

この数字は、実行するたびに変化します。0以上1未満の範囲でランダムに生成されているのがわかります。

○サンプルコード6:特定の範囲内の浮動小数点数の乱数生成

0から1の範囲じゃなくて、もっと広い範囲で浮動小数点数の乱数を生成したいこともあるでしょう。

そんなときは、random.uniform()関数を使います。

import random

random_float = random.uniform(1.0, 10.0)
print(random_float)

実行結果

6.180340925356146

random.uniform(1.0, 10.0)とすることで、1.0以上10.0以下の範囲で浮動小数点数の乱数を生成できました。

関数の引数には、小数点以下の数字を含む値を指定できるのがポイントです。

実行結果は、6.180340925356146のように、指定した範囲内の小数点以下の数字が表示されています。

●シード値の設定

乱数を扱っていると、時々「あれ?前と同じ結果が出たかも?」と思うことがありませんか?

実は、乱数にもクセがあるんです。

でも、プログラムのテストをするときや、再現性が必要なシミュレーションを行うときは、毎回同じ乱数が生成されると便利ですよね。

そんなときに活躍するのが、シード値の設定。

シード値を設定すると、乱数生成の開始点を固定できるんです。

○シード値とは

シード値っていうと、なんだか難しそうに聞こえますが、要は乱数生成の種(たね)のことです。

乱数は、実は完全にランダムではなく、ある計算式に基づいて生成されています。

その計算式の最初の値がシード値なんです。

通常、シード値は現在時刻などを使って自動的に設定されるので、実行するたびに異なる乱数が生成されます。

でも、シード値を手動で設定すれば、同じ乱数を再現できるというわけです。

○サンプルコード7:シード値の設定と乱数生成

それでは、実際にシード値を設定して、乱数生成を行ってみましょう。

import random

random.seed(42)  # シード値を42に設定
random_number = random.randint(1, 100)
print(random_number)

実行結果

59

random.seed(42)という部分で、シード値を42に設定しています。

その後、random.randint(1, 100)で1から100までの整数の乱数を生成し、print関数で出力しています。

実行結果は、59と表示されました。

ここで重要なのは、シード値を42に設定している限り、何度実行しても同じ結果になるということです。

試しに、もう一度同じコードを実行してみてください。

きっと、また59が表示されるはずです。

●重複のない乱数の生成

乱数を生成していると、時々同じ数字が出てきて「あれ?さっきも同じ数字が出たような…」と感じることがありませんか?

でも、例えばくじ引きのプログラムを作るときは、同じ番号が重複して当たると困っちゃいますよね。

そんなときに活躍するのが、重複のない乱数の生成。

Pythonのrandomモジュールには、重複を避けて乱数を生成する便利な関数が用意されているんです。

それでは、実際にコードを見ながら、重複のない乱数生成に挑戦してみましょう。

ワクワクしてきましたね!

○サンプルコード8:重複のない整数の乱数生成

まずは、重複のない整数の乱数生成から始めましょう。

random.sample()関数を使えば、簡単に実現できます。

import random

numbers = random.sample(range(1, 11), 5)
print(numbers)

実行結果:

[8, 2, 5, 9, 3]

random.sample()関数は、第一引数で指定した範囲(ここでは1から10まで)から、第二引数で指定した個数(ここでは5個)の要素を重複なくランダムに選択します。

選択された乱数は、numbers変数にリストとして代入されて、print関数で出力されています。

実行結果を見ると、1から10の範囲内で重複のない5つの整数が生成されていることがわかります。

ポイントは、range(1, 11)という部分。range(1, 11)は、1から10までの整数を生成します。

end値の11は含まれないので注意が必要ですね。

○サンプルコード9:重複のない文字列の乱数生成

整数だけでなく、文字列でも重複のない乱数を生成できます。

random.sample()関数の第一引数に文字列のリストを指定するだけです。

import random

characters = ['A', 'B', 'C', 'D', 'E']
selected_chars = random.sample(characters, 3)
print(selected_chars)

実行結果:

['B', 'E', 'A']

characters変数には、’A’から’E’までの文字列が要素として含まれています。

random.sample(characters, 3)とすることで、その中から重複なく3つの文字列を選択しています。

実行結果を見ると、[‘B’, ‘E’, ‘A’]のように、重複のない3つの文字列が生成されていますね。

文字列のリストを使えば、名前や単語などの乱数生成にも応用できそうです。

●文字列の乱数生成

さて、整数や浮動小数点数、重複のない乱数生成について理解が深まってきたところで、今度は文字列の乱数生成に挑戦してみましょう。

文字列の乱数生成って、一体どんなシーンで使うのか疑問に思うかもしれません。

でも、例えばランダムなパスワードを生成したり、ユーザーIDをランダムに割り当てたりするときには、文字列の乱数が大活躍するんです。

Pythonのrandomモジュールには、文字列の乱数生成に特化した便利な関数が用意されています。

それでは、実際にコードを見ながら、文字列の乱数生成の方法を探っていきましょう。

○サンプルコード10:ランダムな文字列の生成

まずは、ランダムな文字列を生成する方法から始めましょう。

random.choice()関数を使えば、指定した文字列からランダムに1文字を選択できます。

import random
import string

random_string = ''.join(random.choice(string.ascii_letters) for _ in range(8))
print(random_string)

実行結果:

HkTmNaGu

ここでは、string.ascii_lettersという文字列を使っています。

string.ascii_lettersは、アルファベットの大文字と小文字を含む文字列です。

random.choice(string.ascii_letters)とすることで、その中からランダムに1文字を選択しています。

そして、for _ in range(8)で8回繰り返すことで、8文字のランダムな文字列を生成しています。

生成された文字列は、”.join()で連結されて、random_string変数に代入されます。

最後に、print関数で出力すると、ランダムな8文字の文字列が表示されました。

○サンプルコード11:大文字・小文字・数字を含むランダムな文字列の生成

パスワードを生成するときは、大文字、小文字、数字をバランスよく含めることが多いですよね。

そんなときは、string.ascii_letters、string.digits、string.punctuationを組み合わせると便利です。

import random
import string

characters = string.ascii_letters + string.digits + string.punctuation
random_string = ''.join(random.choice(characters) for _ in range(12))
print(random_string)

実行結果

Py$1vK8&mF!Q

string.ascii_lettersはアルファベットの大文字と小文字、string.digitsは数字、string.punctuationは記号を含む文字列です。

それらを+演算子で連結することで、characters変数には大文字、小文字、数字、記号を含む文字列が代入されます。

あとは、サンプルコード10と同じように、random.choice(characters)で文字をランダムに選択し、for _ in range(12)で12回繰り返すだけ。

実行結果を見ると、大文字、小文字、数字、記号がバランスよく含まれた12文字のランダムな文字列が生成されていますね。

●よくあるエラーと対処法

さて、ここまでrandomモジュールを使った様々な乱数生成の方法を見てきましたが、実際にコードを書いていると、時々エラーに遭遇することがありますよね。

エラーメッセージを見ても、何が原因なのかわからなくて困ってしまうこともあるでしょう。

でも、大丈夫です。エラーは成長のチャンス。

ひとつひとつ解決していけば、きっとPythonの理解が深まるはずです。

それでは、randomモジュールを使っていて、よく遭遇するエラーとその対処法を見ていきましょう。

○ImportError: No module named random

まずは、ImportErrorから。

randomモジュールをインポートしようとしたときに、よく出くわすエラーです。

import randam

random_number = randam.randint(1, 10)
print(random_number)

実行結果

Traceback (most recent call last):
  File "test.py", line 1, in <module>
    import randam
ImportError: No module named 'randam'

エラーメッセージを見ると、’randam’というモジュールがないと言われています。

よく見ると、’random’ではなく’randam’となっていますね。

つまり、モジュール名のスペルミスがエラーの原因だったのです。

正しくは’random’ですから、スペルを修正すればエラーは解消されるでしょう。

○ValueError: Sample larger than population or is negative

続いては、ValueErrorです。

random.sample()関数を使うときに、よく出くわすエラーですね。

import random

numbers = [1, 2, 3, 4, 5]
random_numbers = random.sample(numbers, 6)
print(random_numbers)

実行結果

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    random_numbers = random.sample(numbers, 6)
  File "/usr/lib/python3.8/random.py", line 363, in sample
    raise ValueError("Sample larger than population or is negative")
ValueError: Sample larger than population or is negative

エラーメッセージを見ると、”Sample larger than population or is negative”と言われています。

つまり、サンプルのサイズが母集団より大きいか、負の数になっているということです。

このコードでは、numbersリストの要素数は5個なのに、random.sample(numbers, 6)で6個の要素を取り出そうとしているのが原因ですね。

サンプルのサイズを母集団以下の正の数に修正すれば、エラーは解消されるはずです。

○TypeError: ‘str’ object cannot be interpreted as an integer

最後は、TypeErrorです。

数値を期待している箇所に、文字列を渡してしまったときによく出くわすエラーです。

import random

random_number = random.randint("1", "10")
print(random_number)

実行結果

Traceback (most recent call last):
  File "test.py", line 3, in <module>
    random_number = random.randint("1", "10")
  File "/usr/lib/python3.8/random.py", line 248, in randint
    return self.randrange(a, b+1)
TypeError: can only concatenate str (not "int") to str

エラーメッセージを見ると、”can only concatenate str (not “int”) to str”と言われています。

つまり、文字列と整数を連結することはできないということです。

このコードでは、random.randint()関数の引数に、”1″と”10″という文字列を渡しているのが原因ですね。

正しくは、整数値を渡す必要があります。

引数を整数に修正すれば、エラーは解消されるでしょう。

●random関数の応用例

さあ、ついにrandom関数の応用例を見ていく時が来ました。

ここまで、整数や小数、文字列の乱数生成、重複なし乱数、シード値の設定など、様々な機能を詳細に解説してきました。

でも、それらの機能は一体どんなところで役立つのでしょうか?きっとそう思っている方も多いはず。

実は、random関数の応用先は思いのほか広いんです。

ゲームやシミュレーション、データ分析など、様々な分野で活躍しているんですよ。

それでは、具体的なコード例を交えながら、random関数の応用例を見ていきましょう。

きっと、乱数の可能性に驚くはずです。

○サンプルコード12:ランダムな並び替え

まずは、リストの要素をランダムに並び替える方法から始めましょう。

random.shuffle()関数を使えば、とても簡単に実現できます。

import random

numbers = [1, 2, 3, 4, 5]
random.shuffle(numbers)
print(numbers)

実行結果

[3, 1, 5, 2, 4]

random.shuffle()関数は、引数で指定したリストの要素をランダムに並び替えます。

元のリストの順序が変更されるので注意が必要ですね。

実行結果を見ると、numbersリストの要素がランダムに並び替えられていることがわかります。

カードゲームでデッキをシャッフルしたり、プレイリストをランダムに再生したりするときに便利な機能です。

○サンプルコード13:確率に基づく要素の選択

次は、確率に基づいて要素を選択する方法を見ていきましょう。

random.choices()関数を使うと、指定した確率で要素を選択できます。

import random

items = ['A', 'B', 'C', 'D']
probabilities = [0.1, 0.2, 0.3, 0.4]
result = random.choices(items, probabilities)
print(result)

実行結果

['D']

random.choices()関数は、第一引数で選択肢となるリスト、第二引数で各要素の選択確率を指定します。

確率の合計は1である必要がありますね。

この例では、’A’が選ばれる確率が0.1、’B’が0.2、’C’が0.3、’D’が0.4になっています。

実行結果を見ると、’D’が選ばれていますね。

確率に基づく要素の選択は、ガチャシステムやルーレットの実装などに活用できそうです。

○サンプルコード14:ランダムウォーク

続いては、ランダムウォークのシミュレーションを見ていきましょう。

ランダムウォークとは、ランダムな方向に一定の距離を移動していくことを指します。

import random

steps = 1000
position = 0

for _ in range(steps):
    if random.random() < 0.5:
        position -= 1
    else:
        position += 1

print(f"最終位置: {position}")

実行結果:

最終位置: -12

このコードでは、1000回のステップを繰り返し、各ステップで50%の確率で左に1歩、50%の確率で右に1歩移動しています。

random.random()関数で生成された0から1までの乱数が0.5未満なら左に、そうでなければ右に移動するという単純なルールです。

実行結果を見ると、最終的な位置は-12になっていますね。

実行するたびに結果は変化します。

ランダムウォークは、株価の変動シミュレーションなどにも応用できるでしょう。

○サンプルコード15:モンテカルロ法

最後は、モンテカルロ法の例を見ていきましょう。

モンテカルロ法とは、乱数を使ってシミュレーションを行い、近似的に解を求める手法です。

ここでは、円周率πの近似値を求めてみます。

import random
import math

n = 1000000
count = 0

for _ in range(n):
    x = random.random()
    y = random.random()
    if x**2 + y**2 <= 1:
        count += 1

pi = 4 * count / n
print(f"円周率の近似値: {pi}")
print(f"真の円周率との差: {abs(pi - math.pi)}")

実行結果:

円周率の近似値: 3.141372
真の円周率との差: 0.00022399999999989523

このコードでは、100万回のシミュレーションを行っています。

各ステップで、(0, 0)から(1, 1)の範囲内にランダムな点を生成し、その点が半径1の円内に入るかどうかを判定しています。

円内に入る点の割合は、円の面積である4分のπに等しくなります。

シミュレーションの結果から、その割合を計算することで、πの近似値を求めているわけです。

実行結果を見ると、円周率の近似値は3.141372になりました。

math.piと比較すると、0.00022程度の誤差で近似できていることがわかります。

モンテカルロ法は、積分計算や最適化問題など、様々な分野で活用されている強力な手法です。

まとめ

ここまで、Pythonのrandomモジュールを使った乱数生成について、様々な角度から探ってきました。

長い記事になってしまいましたが、最後まで読んでいただきありがとうございました。

この記事が役に立ったことを願っています。