[解決!Python]べき乗を計算するには(**演算子、pow関数、math.pow関数)解決!Python

Pythonでべき乗を計算するには**演算子、組み込みのpow関数、mathモジュールのpow関数を使える。それらの使い方と、振る舞いの違いを紹介する。

» 2024年07月23日 05時00分 公開
[かわさきしんじDeep Insider編集部]
「解決!Python」のインデックス

連載目次

# べき乗を計算する3つの方法
base = 2
exp = 10

# **演算子を使う
r = base ** exp
print(r)  # 1024

# 組み込みのpow関数を使う
r = pow(base, exp)
print(r)  # 1024

# mathモジュールのpow関数を使う
import math

r = math.pow(base, exp)
print(r)  # 1024.0:math.pow関数では引数は浮動小数点数値に変換される

# 組み込みのpow関数ではべき乗した結果をmodで割った剰余を求めることも可能
mod = 15

r0 = pow(base, exp, mod)
r1 = base ** exp % mod  # **演算子の方が優先順位が高い

print(f'pow({base}, {exp}, {mod}): {r0}'# pow(2, 10, 15): 4
print(f'{base} ** {exp} % {mod}: {r1}'# 2 ** 10 % 15: 4

# 剰余を求めるときには全ての引数が整数値でなければならない
r = pow(2.0, exp, mod)  # TypeError

# math.pow関数は引数を浮動小数点数値に変換する
base = 2
exp = 60

r0 = base ** exp
r1 = math.pow(base, exp)

print(f'{base} ** {exp}: {r0}'# 2 ** 60: 1152921504606846976
print(f'math.pow({base}, {exp}): {r1}'# math.pow(2, 60): 1.152921504606847e+18

# 複素数値(complex型の値)の計算にmath.pow関数は使えない
base = 1# 虚数単位(二乗すると-1になる)
exp = 2

r = base ** exp  # OK
print(r)  # (-1+0j)

r = pow(base, exp)  # OK
print(r)  # (-1+0j)

r = math.pow(base, exp)  # TypeError

# 計算結果が複素数値になる値を与えると、math.pow関数はValueErrorを発生させる
import cmath

base = -1
exp = 0.5

r = base ** exp  # OK
print(r)  # (6.123233995736766e-17+1j)
print(r ** 2# (-1+1.2246467991473532e-16j)
print(cmath.isclose(r ** 2, -1))  # True

r = pow(base, exp)  # OK
print(r)  # (6.123233995736766e-17+1j)
print(r ** 2# (-1+1.2246467991473532e-16j)
print(cmath.isclose(r ** 2, -1))  # True

r = math.pow(base, exp)  # ValueError


関数/演算子 説明
base ** exp baseexpを計算する
pow(base, exp, mod=None) baseexpを計算する。modを指定すると、baseexpをmodで割った剰余を計算する
math.pow(base, exp) baseexpを計算する。baseとexpはfloat型に変換される。複素数は扱えない
べき乗を計算する3つの演算子/関数

べき乗を計算する3つの方法

 Pythonでべき乗を計算するには主に以下の3つの方法がある。

  • **演算子を使う
  • Pythonに組み込みのpow関数を使う
  • mathモジュールのpow関数を使う

 べき乗を計算するだけであれば、どれを使っても答えは変わらない。ただし、pow関数はべき乗をmodパラメーターの値で割った剰余を求められる、math.pow関数は引数をfloat型の値に変換する、また「IEEE 754標準に可能な限り」従うようになっているなどの差がある点には注意しよう。

 3つの演算子/関数の基本的な使い方を以下に示す。

base = 2
exp = 10

# **演算子を使う
r = base ** exp
print(r)  # 1024

# 組み込みのpow関数を使う
r = pow(base, exp)
print(r)  # 1024

# mathモジュールのpow関数を使う
import math

r = math.pow(base, exp)
print(r)  # 1024.0:math.pow関数では引数は浮動小数点数値に変換される


 上のコードはいずれも210を計算するが、**演算子を使う方法と組み込みのpow関数ではその答えは整数になっている。一方、math.pow関数は引数を浮動小数点数値に変換するので、答えも1024.0と浮動小数点数値になっている。

 組み込みのpow関数では3つ目の引数(mod)を与えることも可能だ。この場合は、べき乗(「base ** exp」または「pow(base, exp)」)の計算結果をmodで割った剰余が返される。以下に例を示す。

mod = 15

r0 = pow(base, exp, mod)
r1 = base ** exp % mod  # **演算子の方が優先順位が高い

print(f'pow({base}, {exp}, {mod}): {r0}'# pow(2, 10, 15): 4
print(f'{base} ** {exp} % {mod}: {r1}'# 2 ** 10 % 15: 4


 この例では210を15で割った余り(剰余)が得られる。リスト中に「base ** exp % mod」という式があるが、**演算子は優先度が%演算子よりも高いので、べき乗が先に計算される点に注意。

 なお、組み込みのpow関数を使って、べき乗の剰余を計算するときには3つの引数が全て整数値である必要がある。以下はやはり210を15で割った剰余を求めようとしているが、第1引数が2.0と浮動小数点数値になっているのでTypeError例外が発生する。

r = pow(2.0, exp, mod)  # TypeError


 既に見たが、math.pow関数は引数を浮動小数点数値に変換し、その計算結果も浮動小数点数値になる。そのため、math.pow関数を使ってべき乗を計算した結果が大きな値になると丸めが発生することがある。例えば、以下のコードでは260を求めようとしている。

base = 2
exp = 60

r0 = base ** exp
r1 = math.pow(base, exp)

print(f'{base} ** {exp}: {r0}'# 2 ** 60: 1152921504606846976
print(f'math.pow({base}, {exp}): {r1}'# math.pow(2, 60): 1.152921504606847e+18


 **演算子では260の結果が整数値として得られているが、math.pow関数を使った計算では浮動笑点数値となり**演算子を使った場合の結果とは異なる値になっている点に注目されたい。

 また、math.pow関数は引数をfloat型の値に変換するが、複素数値を与えた場合には、それらをfloat型に変換できないのでTypeError例外が発生する点にも注意しよう。以下に例を示す。

base = 1# 虚数単位(二乗すると-1になる)
exp = 2

r = base ** exp  # OK
print(r)  # (-1+0j)

r = pow(base, exp)  # OK
print(r)  # (-1+0j)

r = math.pow(base, exp)  # TypeError


 上記のコードはいずれも複素数値「0+1i」を二乗しようとしている(Pythonでは虚数部は「j」を付加して示す)。**演算子と組み込みのpow関数では正しくその二乗が-1であると得られている。しかし、math.pow関数ではTypeError例外が発生する(mathモジュールは複素数値をサポートしていない。複素数値を扱うにはcmathモジュールを使用する。ただし、cmathモジュールにはpow関数はない)。

 同様に、計算結果が複素数となるような値をmath.pow関数に与えるとValueError例外が発生する。以下に例を示す。

import cmath

base = -1
exp = 0.5

r = base ** exp  # OK
print(r)  # (6.123233995736766e-17+1j)
print(r ** 2# (-1+1.2246467991473532e-16j)
print(cmath.isclose(r ** 2, -1))  # True

r = pow(base, exp)  # OK
print(r)  # (6.123233995736766e-17+1j)
print(r ** 2# (-1+1.2246467991473532e-16j)
print(cmath.isclose(r ** 2, -1))  # True

r = math.pow(base, exp)  # ValueError


 上のコードは-10.5つまり-1の平方根(0+1i)を求めようとしている。**演算子とpow関数ではだいたいそれに近い値を得られているが、math.pow関数ではValueError例外が発生する。

 単にべき乗を求めるだけでも3つの方法のそれぞれで振る舞いが異なるので注意しよう。IEEE 754標準に可能な限り準拠した結果が必要であればmath.pow関数を使い、そうでなければ**演算子か組み込みのpow関数を使うというのが、一つの基準といえるかもしれない。

「解決!Python」のインデックス

解決!Python

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

AI for エンジニアリング
「サプライチェーン攻撃」対策
1P情シスのための脆弱性管理/対策の現実解
OSSのサプライチェーン管理、取るべきアクションとは
Microsoft & Windows最前線2024
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。