note.nkmk.me

NumPyで三角関数(sin, cos, tan, arcsin, arccos, arctan)

Posted: 2020-10-18 / Tags: Python, NumPy, 算数・数学

NumPyでは、配列numpy.ndarrayの各要素に対して三角関数(sin, cos, tan)および逆三角関数(arcsin, arccos, arctan)を計算する関数が提供されている。

ここでは以下の内容について説明する。

  • 円周率(パイ): np.pi
  • 共通の話題
    • 対象となる型
    • 値の丸め
  • 角度変換(ラジアン、度)
    • 度からラジアン: np.radians(), np.deg2rad()
    • ラジアンから度: np.degrees(), np.rad2deg()
  • 正弦、逆正弦: np.sin(), np.arcsin()
  • 余弦、逆余弦: np.cos(), np.arccos()
  • 正接、逆正接: np.tan(), np.arctan(), np.arctan2()
  • np.arctan()np.arctan2()の違いと負のゼロ

三角関数はPythonの標準ライブラリmathモジュールでも計算可能。

NumPyでは、三角関数のほか、np.sinh(), np.cosh(), np.tanh(), np.arcsinh(), np.arccosh(), np.arctanh()といった双曲線関数も提供されている。

スポンサーリンク

円周率(パイ): np.pi

円周率(パイ、π)はnp.piで定義されている。

import numpy as np

print(np.__version__)
# 1.19.0

print(np.pi)
# 3.141592653589793

共通の話題

それぞれの関数に共通する内容として、各関数に引数として指定できる型および値の丸めについて説明する。

対象となる型

度をラジアンに変換するnp.radians()を例とするが、np.sin()などほかの関数でも同じ。

引数にスカラー値(数値)を指定すると、スカラー値が返される。

print(np.radians(180))
# 3.141592653589793

print(type(np.radians(180)))
# <class 'numpy.float64'>

引数にnumpy.ndarrayを指定すると、要素ごとに処理されたnumpy.ndarrayが返される。

a = np.array([0, 90, 180])
print(type(a))
# <class 'numpy.ndarray'>

print(np.radians(a))
# [0.         1.57079633 3.14159265]

print(type(np.radians(a)))
# <class 'numpy.ndarray'>

numpy.ndarrayだけでなく、リストなどのいわゆるarray-likeオブジェクトも指定可能。返り値はnumpy.ndarrayなので注意。

l = [0, 90, 180]
print(type(l))
# <class 'list'>

print(np.radians(l))
# [0.         1.57079633 3.14159265]

print(type(np.radians(l)))
# <class 'numpy.ndarray'>

numpy.ndarrayとリストの相互変換については以下の記事を参照。

値の丸め

無理数である円周率を用いるので、三角関数の計算には誤差が生じる場合がある。

値を丸めたい場合はnp.round()またはnp.round_(), np.around()を使う。どれでも結果は同じ。第二引数に返り値の小数点以下の桁数(デフォルトは0)を指定する。

公式ドキュメントにはnp.round()は記載されていないが、少なくともバージョン1.19.0時点では使える。

print(np.radians(a))
# [0.         1.57079633 3.14159265]

print(np.round(np.radians(a)))
# [0. 2. 3.]

print(np.round(np.radians(a), 2))
# [0.   1.57 3.14]

round()numpy.ndarrayのメソッドとしても提供されている。

なお、Pythonの組み込み関数round()と同じく、NumPyにおけるnp.round()np.around()なども四捨五入ではなく偶数への丸めとなるので注意。

三角関数の計算で誤差が生じる具体例は以下の通り。値を丸めたい場合はnp.round()などを使えばよい。

print(np.sin(np.radians(30)))
# 0.49999999999999994

print(np.round(np.sin(np.radians(30)), 1))
# 0.5

numpy.ndarrayとして出力すると要素の値が丸められて表示される場合があるが、あくまでも表示上丸められているだけで、値自体はそのまま。

print(np.sin(np.radians([0, 30, 90])))
# [0.  0.5 1. ]

print(np.sin(np.radians([0, 30, 90]))[1])
# 0.49999999999999994

print()で出力される桁数などの設定はnp.set_printoptions()で変更できる。

np.set_printoptions(precision=20)
print(np.sin(np.radians([0, 30, 90])))
# [0.                  0.49999999999999994 1.                 ]

np.set_printoptions(precision=8)  # reset to default

以降のサンプルコードではデフォルトprecision=8で実行した結果を示す。

角度変換(ラジアン、度)

NumPyにおけるnp.sin(), np.arcsin()などの三角関数・逆三角関数では、角度をラジアン(弧度)で表す。

度からラジアン: np.radians(), np.deg2rad()

度からラジアンへの変換はnp.radians()またはnp.deg2rad()。どちらでも結果は同じ。

print(np.radians([0, 90, 180]))
# [0.         1.57079633 3.14159265]

print(np.deg2rad([0, 90, 180]))
# [0.         1.57079633 3.14159265]

ラジアンから度: np.degrees(), np.rad2deg()

ラジアンから度への変換はnp.degrees()またはnp.rad2deg()。どちらでも結果は同じ。

print(np.degrees([0, np.pi / 2, np.pi]))
# [  0.  90. 180.]

print(np.rad2deg([0, np.pi / 2, np.pi]))
# [  0.  90. 180.]

正弦、逆正弦: np.sin(), np.arcsin()

正弦(サイン、sin)はnp.sin()、逆正弦(アークサイン、arcsin)はnp.arcsin()

print(np.sin(np.radians([0, 30, 90])))
# [0.  0.5 1. ]

print(np.degrees(np.arcsin([0, 0.5, 1])))
# [ 0. 30. 90.]

余弦、逆余弦: np.cos(), np.arccos()

余弦(コサイン、cos)はnp.cos()、逆余弦(アークコサイン、arccos)はnp.arccos()

print(np.cos(np.radians([0, 60, 90])))
# [1.000000e+00 5.000000e-01 6.123234e-17]

print(np.round(np.cos(np.radians([0, 60, 90])), 1))
# [1.  0.5 0. ]

print(np.degrees(np.arccos([0, 0.5, 1])))
# [90. 60.  0.]

正接、逆正接: np.tan(), np.arctan(), np.arctan2()

正接(タンジェント、tan)はnp.tan()、逆正接(アークタンジェント、arctan)はnp.arctan()またはnp.arctan2()np.arctan2()については後述。

print(np.tan(np.radians([0, 45, 90])))
# [0.00000000e+00 1.00000000e+00 1.63312394e+16]

print(np.degrees(np.arctan([0, 1, np.inf])))
# [ 0. 45. 90.]

np.infは無限大を表す。

np.arctan()とnp.arctan2()の違いと負のゼロ

np.arctan()np.arctan2()はどちらも逆正接を返す関数だが、引数の数と返り値の範囲が異なる。

np.arctan(x)は引数が一つでarctan(x)をラジアンで返す。返り値は-pi / 2からpi / 2(-90度から90度)の間になる。

print(np.degrees(np.arctan([-np.inf, -1, 0, 1, np.inf])))
# [-90. -45.   0.  45.  90.]

np.arctan2(y, x)は引数が二つで、arctan(y / x)をラジアンで返す。この角度は、極座標平面において原点から座標(x, y)へのベクトルがx軸の正の方向となす角度(偏角)であり、返り値は-piからpi(-180度から180度)の間になる。

第2象限、第3象限における角度も正しく取得できるので、極座標平面で考える場合はnp.arctan()よりもnp.arctan2()のほうが適当。

引数の順番がx, yではなくy, xなので注意。

print(np.degrees(np.arctan2(-1, 1)))
# -45.0

print(np.degrees(np.arctan2(1, -1)))
# 135.0

第一引数、第二引数にはnumpy.ndarrayやリストなどのarray-likeオブジェクトも指定できる。対応する要素のペアで値が算出される。

print(np.degrees(np.arctan2([0, 1, 1, 1, 0],
                            [0, 1, 0, -1, -1])))
# [  0.  45.  90. 135. 180.]

print(np.degrees(np.arctan2([0, -1, -1, -1, 0],
                            [0, 1, 0, -1, -1])))
# [   0.  -45.  -90. -135.  180.]

上の例のように、x軸の負の方向(yが0でxが負の値)はpi(180度)となるが、yが負のゼロのときは-pi(-180度)となる。符号を厳密に処理したい場合は要注意。

print(np.degrees(np.arctan2(0, -1)))
# 180.0

print(np.degrees(np.arctan2(-0.0, -1.0)))
# -180.0

なお、負のゼロは浮動小数点数floatで指定可能。整数intでは負のゼロを扱えないので-00として扱われる。

print(np.degrees(np.arctan2(-0, -1)))
# 180.0

上の例のように、ゼロの符号(正負)によって結果の符号が変わる場合はほかにもある。結果の符号は、負のゼロを負の微小な値とイメージすると理解しやすい。

print(np.degrees(np.arctan2([0.0, -0.0, 0.0, -0.0],
                            [0.0, 0.0, -0.0, -0.0])))
# [   0.   -0.  180. -180.]

print(np.sin(-0.0))
# -0.0

print(np.arcsin(-0.0))
# -0.0

print(np.tan(-0.0))
# -0.0

print(np.arctan(-0.0))
# -0.0
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事