私の理解では、出力が-pi/2からpi/2に制限されているため、atan2()
自体が常に正しいシータを判別できるとは限らないため、atan()
関数はプログラミング言語に存在します。
この場合、同じ問題がasin()
とacos()
の両方に当てはまり、どちらも範囲が制限されているため、asin2()
がないのはなぜですか。およびacos2()
関数?
まず、構文はatan(y/x)
ではなくatan2(y, x)
であり、atan2(y/x)
ではないことに注意してください。分割を実行しないことで追加情報、最も重要なのはx
とy
の個々の記号を提供するため、これは重要です。 x
座標とy
座標が別々にわかっている場合は、象限を含む角度がわかります。
tan(θ) = y/x
からsin(θ) = y/sqrt(x²+y²)
に移動する場合、逆演算asin
はy
とsqrt(x²+y²)
を取り、それを組み合わせて次のようになります。角度に関するいくつかの情報。ここでは、除算を自分で実行するか、架空の_asin2
_関数で処理するかは関係ありません。分母は常に正であるため、分割された引数には、個別の分子と分母に含まれるのと同じ量の情報が含まれます。 (少なくとも、ゼロによる除算が正しく署名された無限大につながるIEEE環境では。)
y
座標と斜辺sqrt(x²+y²)
がわかっている場合は、角度の正弦はわかりますが、負と正のx
値。同様に、x
座標と斜辺がわかっている場合は、角度の余弦はわかりますが、y
値の符号はわかりません。
したがって、_asin2
_と_acos2
_は、少なくとも明白な方法では、数学的に実行可能ではありません。ある種の記号が斜辺にエンコードされていれば、状況は異なるかもしれませんが、そのような記号が自然に発生する状況は考えられません。
このように簡単な用語で説明します。
次の説明については、この画像を参照してください。
タスク:範囲全体で正しい角度を追跡する関数を選択します_-180 < θ < 180
_
試行1:sin()
は、第1象限と第2象限sin(30) = sin(150) = 0.5
で正です。 sin()
で象限の変化を追跡するのは簡単ではありません。
したがって、asin2()
は実行できません。
試行2:cos()
は、第1象限と第4象限cos(60) = sin(300) = 0.5
で正です。また、cos()
で象限の変化を追跡するのは簡単ではありません。
したがって、acos2()
は再び実行可能ではありません。
試行3:tan()
は、第1象限と第3象限で、興味深い順序で正です。
これは、第1象限で正、第2象限で負、第3象限で正、第4象限で負、ラップアラウンド第1象限で正になります。
tan(45) = 1
、tan(135) = -1
、tan(225) = 1
、tan(315) = -1
、およびtan(360+45) = 1
など。やあ!象限の変化を追跡できます。
明確な範囲が_-180 < θ < 180
_であることに注意してください。また、上記の45度の増分の例では、シーケンスが_1,-1,..
_の場合、角度は反時計回りになり、シーケンスが_-1,1,..
_の場合、時計回りになります。このアイデアは方向性を解決するはずです。
したがって、atan2()
が私たちの選択になります。
3D空間でベクトルの回転を行う場合など、「acos2」のような関数が必要になる場合があります。そのような状況では、次のチェックを実行するだけの独自のacos2関数をハードコーディングします。
x_perp=sqrt(x*x+y*y)
r=sqrt(x*x+y*y+z*z)
if(x_perp.gt.0.0d0) then
phi=acos(x/x_perp)
else
phi=0.0d0
endif
if(y.lt.0.0d0) phi=2.0d0*pi-phi
theta=acos(z/r)
ここで、シータとファイは通常の球面座標であり、x、y、zはデカルト座標です。この問題は、yが負の場合に発生し、ファイに位相シフトが必要です。シータにはそのような問題はありません。
asin(y,x)
acos(y,x)
はそれぞれatan(y,x)
と同じパラメーターを取り、それぞれが同じ答えを与えるからです。それぞれが等しく有効ですが、必要な関数は1つだけです。
不明確さは(atan2の)名前から生じます。その関数は、(正の)x軸を使用して_given x and y, computes the angle
_(原点からこの点までの線で作成)します。 angle_from(x,y)
のような名前がおそらくより適切だったでしょう。