Pythonで三角関数を計算(sin, cos, tan, arcsin, arccos, arctan)
Pythonの数学関数の標準モジュールmathを使うと、三角関数(sin, cos, tan)および逆三角関数(arcsin, arccos, arctan)の計算ができる。
mathモジュールをインポートして使う。
import math
NumPyにおける三角関数については以下の記事を参照。
円周率(π): math.pi
円周率(パイ、π)はmathモジュールの中で定数として用意されている。math.piで表す。
print(math.pi)
# 3.141592653589793
角度変換(ラジアン、度): math.degrees(), math.radians()
mathモジュールの三角関数および逆三角関数では、角度の単位としてラジアンを使う。
ラジアン(弧度法)と度(度数法)を変換するにはmath.degrees()とmath.radians()を使う。
ラジアンから度に変換するのがmath.degrees()で、度からラジアンに変換するのがmath.radians()。
print(math.degrees(math.pi))
# 180.0
print(math.radians(180))
# 3.141592653589793
正弦、逆正弦: math.sin(), math.asin()
正弦(サイン、sin)を求める関数はmath.sin()、逆正弦(アークサイン、arcsin)を求める関数はmath.asin()。
30度の正弦を求める例を示す。math.radians()で度をラジアンに変換している。
sin30 = math.sin(math.radians(30))
print(sin30)
# 0.49999999999999994
30度の正弦は0.5だが、無理数である円周率を正確に計算できないので誤差が生じる。
適当な桁数で丸めるには組み込み関数round()を使う。第二引数に小数点以下何桁に丸めるか指定する。四捨五入ではなく偶数への丸めなので注意。
print(round(sin30, 1))
# 0.5
比較したい場合は誤差を考慮するmath.isclose()を使う方法もある。
print(math.isclose(sin30, 0.5))
# True
同様に0.5の逆正弦を求める例を示す。math.asin()が返すのはラジアンなので、math.degrees()で度に変換している。
asin05 = math.degrees(math.asin(0.5))
print(asin05)
# 29.999999999999996
print(round(asin05, 1))
# 30.0
余弦、逆余弦: math.cos(), math.acos()
余弦(コサイン、cos)を求める関数はmath.cos()、逆余弦(アークコサイン、arccos)を求める関数はmath.acos()。
60度の余弦と0.5の逆余弦を求める例を示す。
print(math.cos(math.radians(60)))
# 0.5000000000000001
print(math.degrees(math.acos(0.5)))
# 59.99999999999999
適当な桁で丸めたい場合は、上述のように組み込み関数round()を使う。
正接、逆正接: math.tan(), math.atan(), math.atan2()
正接(タンジェント、tan)を求める関数はmath.tan()、逆正接(アークタンジェント、arctan)を求める関数はmath.atan()またはmath.atan2()。math.atan2()については後述。
45度の正接と1の逆正接を求める例を示す。
print(math.tan(math.radians(45)))
# 0.9999999999999999
print(math.degrees(math.atan(1)))
# 45.0
適当な桁で丸めたい場合は、上述のように組み込み関数round()を使う。
math.atan()とmath.atan2()の違い
math.atan()とmath.atan2()はどちらも逆正接を返す関数だが、引数の数と返り値の範囲が異なる。
math.atan(x)の返り値は-90度から90度
math.atan(x)は引数が一つで、arctan(x)をラジアンで返す。返り値は-pi / 2からpi / 2(-90度から90度)の間になる。
print(math.degrees(math.atan(0)))
# 0.0
print(math.degrees(math.atan(1)))
# 45.0
print(math.degrees(math.atan(-1)))
# -45.0
print(math.degrees(math.atan(math.inf)))
# 90.0
print(math.degrees(math.atan(-math.inf)))
# -90.0
上の例のmath.infは無限大を表す。
math.atan2(y, x)の返り値は-180度から180度
math.atan2(y, x)は引数が二つで、arctan(y / x)をラジアンで返す。
この角度は、原点から座標(x, y)へのベクトルがx軸の正の方向となす角度(偏角)であり、返り値は-piからpi(-180度から180度)の間になる。
第2象限・第3象限での角度も正しく計算できるので、偏角を求めたい場合はmath.atan()よりもmath.atan2()のほうが適当。
引数の順番がx, yではなくy, xなので注意。
print(math.degrees(math.atan2(0, 1)))
# 0.0
print(math.degrees(math.atan2(1, 1)))
# 45.0
print(math.degrees(math.atan2(1, 0)))
# 90.0
print(math.degrees(math.atan2(1, -1)))
# 135.0
print(math.degrees(math.atan2(0, -1)))
# 180.0
print(math.degrees(math.atan2(-1, -1)))
# -135.0
print(math.degrees(math.atan2(-1, 0)))
# -90.0
print(math.degrees(math.atan2(-1, 1)))
# -45.0
負のゼロ
math.atan2(y, x)において、上の例のように、x軸の負の方向(yが0でxが負の値)はpi(180度)となるが、yが負のゼロのときは-pi(-180度)となる。符号を厳密に処理したい場合は要注意。
print(math.degrees(math.atan2(-0.0, -1)))
# -180.0
負のゼロは以下のような演算の結果として発生する。
print(-1 / math.inf)
# -0.0
print(-1.0 * 0.0)
# -0.0
整数intでは負のゼロとして扱われない。
print(-0.0)
# -0.0
print(-0)
# 0
x, yがどちらもゼロ(原点)の場合も、その符号によって結果が異なる。
print(math.degrees(math.atan2(0.0, 0.0)))
# 0.0
print(math.degrees(math.atan2(-0.0, 0.0)))
# -0.0
print(math.degrees(math.atan2(-0.0, -0.0)))
# -180.0
print(math.degrees(math.atan2(0.0, -0.0)))
# 180.0
math.atan2()だけでなくmath.sin()やmath.asin(), math.tan(), math.atan()など、負のゼロによって結果の符号が変わる例は他にもある。符号を厳密に処理したい場合は要注意。
print(math.sin(0.0))
# 0.0
print(math.sin(-0.0))
# -0.0
print(math.asin(0.0))
# 0.0
print(math.asin(-0.0))
# -0.0
print(math.tan(0.0))
# 0.0
print(math.tan(-0.0))
# -0.0
print(math.atan(0.0))
# 0.0
print(math.atan(-0.0))
# -0.0
print(math.atan2(0.0, 1.0))
# 0.0
print(math.atan2(-0.0, 1.0))
# -0.0