非負整数nの階乗はn!と表記され、n以下の全ての正の整数の積です。例えば、5! = 5 × 4 × 3 × 2 × 1 = 120です。階乗は組合せ論や確率論において基本的な概念です。この記事では、Pythonで階乗を計算する3つの方法、反復処理、再帰処理、そして最適化されたmath.factorial()
関数の使用方法を解説します。
目次
反復処理による階乗の計算
反復処理は簡単なアプローチです。ループを使って数値を順番に掛け算します。
def factorial_iterative(n):
"""非負整数の階乗を反復処理で計算します。
Args:
n: 非負整数。
Returns:
nの階乗。nが0の場合は1を返します。
nが負数の場合はValueErrorを発生させます。
"""
if n < 0:
raise ValueError("階乗は負の数では定義されていません。")
elif n == 0:
return 1
else:
result = 1
for i in range(1, n + 1):
result *= i
return result
# 例
number = 5
result = factorial_iterative(number)
print(f"{number}の階乗は{result}です") # 出力: 5の階乗は120です
この方法は効率的で理解しやすく、再帰処理に固有のスタックオーバーフローの問題を回避できます。
再帰処理による階乗の計算
再帰処理は簡潔な代替手段を提供します。再帰関数は、ベースケース(n = 0、0! = 1)に到達するまで自分自身を呼び出します。
def factorial_recursive(n):
"""非負整数の階乗を再帰処理で計算します。
Args:
n: 非負整数。
Returns:
nの階乗。nが0の場合は1を返します。
nが負数の場合はValueErrorを発生させます。
"""
if n < 0:
raise ValueError("階乗は負の数では定義されていません。")
elif n == 0:
return 1
else:
return n * factorial_recursive(n - 1)
# 例
number = 5
result = factorial_recursive(number)
print(f"{number}の階乗は{result}です") # 出力: 5の階乗は120です
エレガントですが、大きなnに対しては再帰処理の方が遅くなる可能性があり、増加するコールスタックのためにPythonの再帰深度制限に達する可能性があります。
math.factorial()
関数の使用
Pythonのmath
モジュールは、高度に最適化されたfactorial()
関数を提供しています。
import math
def factorial_math(n):
"""math.factorial()を使って階乗を計算します。
Args:
n: 非負整数。
Returns:
nの階乗。
nが負数または整数でない場合はValueErrorを発生させます。
"""
if not isinstance(n, int) or n < 0:
raise ValueError("入力は非負整数でなければなりません。")
return math.factorial(n)
# 例
number = 5
result = factorial_math(number)
print(f"{number}の階乗は{result}です") # 出力: 5の階乗は120です
これは、その効率性、堅牢性、そして大きな数値の処理(最適化されたCコードを活用)において推奨されるアプローチです。
手法の比較
反復処理と再帰処理は教育的な価値を提供しますが、math.factorial()
は、実用的なアプリケーションにおいて、パフォーマンスとエラー処理に関して一般的に優れています。選択は状況によります。教育目的であれば、反復処理または再帰処理の方が適している場合がありますが、本番コードでは、最適化された組み込み関数の利点が大きいです。