べき乗は、べき根はです。では、pythonではどう書くのでしょうか。
2乗とかsqrtくらいはわかっても、n乗根あたりになるとすぐ出てこないという人も多いのでは? そこで、説明を書きます。
目次
スポンサーリンク
組み込み関数powを使う方法
powという組み込み関数があります。まあ、要は達します。
>>> pow(2, 10) 1024 >>> pow(0.5, 10) 0.0009765625 >>> pow(1.5, 3.5) 4.133513940946613
見たところ浮動小数点でも大丈夫。
ドキュメントによると、第三引数を指定することで「x の y 乗に対する z の剰余」を計算できるそうですが、何に使えるのでしょうかね・・・。
2018年11月26日追記:
第三引数の件についてコメントでご指摘をいただきました。これを効率的に計算できることで、公開鍵暗号へ応用できるということのようです。
記事の中で「第三引数を指定することで「x の y 乗に対する z の剰余」を計算できる」のが何のためだろうと書かれていたので、回答になるかもと思いコメントします。
共通鍵暗号の鍵を通信相手と交換する方法に、デフィー・ヘルマン鍵交換という方式があります。その方式では、
(1) Ya = r の Xa乗 に対する q の余剰(Ya: ユーザaの公開鍵, r: qの原始根, Xa: ユーザaの秘密鍵, q: 素数)
(2) K = Ya の Xb乗 に対する q の余剰(K: 共通鍵, Ya: ユーザaの公開鍵, Xb: ユーザbの秘密鍵, q: 素数)
という計算が出てきます。powを使えば例えば(1)は Ya = pow (r, Xa, q) だけで計算できるということです。
(tomoさんのコメントより引用)
関連しそうなwikipediaのページを貼っておきます。
べき乗演算子を使う方法
べき乗の計算では、pow関数と同じことが演算子でもできます。
>>> 2**10 1024 >>> 0.5**10 0.0009765625 >>> 1.5**3.5 4.133513940946613
powを多用すると式がごちゃごちゃするので、こちらを使いたいところです。
ただ、罠があるようです。
Python のべき乗演算子に潜む罠 | CUBE SUGAR STORAGE
単項演算子の-などと組み合わせる場合、べき乗演算子が先に評価されます。どういうこと? と思うかもしれませんが、要するに
>>> -1**2 # WTF!? -1 >>> -(1**2) # つまりはこういうこと -1 >>> (-1)**2 # 本当に欲しかったもの 1
思い通りの結果を得たければカッコを多用すべきであり、そうするとなんかpowでも良いような気もしてきます。
numpyに頼る方法
np.powerがあります。
>>> np.power(2, 10) 1024 >>> np.power(0.5, 10) 0.0009765625 >>> np.power(1.5, 3.5) 4.133513940946613
見たところ、型の取扱も含めてほぼ同じ。まあ、これを単体で使うメリットは特に感じません。numpy配列を相手にするなら、ありかも(ただしnumpy配列にべき乗演算子を使うという選択肢もある)。なお、片方が配列で片方がスカラー、とか配列同士、というケースでは、
>>> import numpy as np >>> np.power([1,2,3], 2) array([1, 4, 9]) >>> np.power(2, [1,2,3]) array([2, 4, 8]) >>> np.power([1,2,3], [4,5,6]) array([ 1, 32, 729])
こんな扱いになります。特に難しいことはないです。
n乗根について
n乗根(べき根)がわからなかった人は、を思い出しましょう。
>>> 2**10 # べき乗(10乗) 1024 >>> 1024**(1/10) # べき根(10乗根) 2.0
小数のべき乗が計算できれば、べき根も計算できるということです。
どれが速いの?
timeitで簡単に比較してみます。私はIPython使いではないので、モジュールimportで使います。
>>> import numpy as np >>> import timeit >>> timeit.timeit(lambda : [[x**y for y in range(30)] for x in range(30)], number=1000) 0.37399847699998645 >>> timeit.timeit(lambda : [[pow(x,y) for y in range(30)] for x in range(30)], number=1000) 0.4485901359998934 >>> timeit.timeit(lambda : [[np.power(x,y) for y in range(30)] for x in range(30)], number=1000) 1.3186961119999978
スカラーに対してはべき乗演算子一択。
numpy配列だと、べき乗演算子とnp.powerはどちらが上でしょうか。
>>> timeit.timeit(lambda : np.arange(1000)**np.arange(1000), number=100000) 1.4120757860000595 >>> timeit.timeit(lambda : np.power(np.arange(1000), np.arange(1000)), number=100000) 1.402805570000055
そもそも冗談みたいに速いんですが(numberに注目)、速度差自体は計測誤差レベル。一番コアな部分は同じ処理なのでしょう。
まとめ
pythonではべき乗・べき根を計算する方法が何通りかあります。とはいえ、べき乗演算子で大抵の用途では用が済むようなので、罠に気をつけて(負の数が絡むときだけ気をつける)使えば良いと思いました。
あと、numpyはやっぱりすごいなぁ・・・