On this page
Inverse Trig Functions
The idea
Forward trig: angle → ratio. Inverse trig: ratio → angle.
$$
\theta = \arcsin x \iff \sin\theta = x, \qquad
\theta = \arccos x \iff \cos\theta = x, \qquad
\theta = \arctan x \iff \tan\theta = x
$$
Also written \(\sin^{-1}, \cos^{-1}, \tan^{-1}\) — the \(-1\) means inverse function, not reciprocal (\(\sin^{-1}x \ne 1/\sin x = \csc x\)).
Restricted ranges (principal values)
Since \(\sin\) repeats, inverses return one canonical angle:
| Function | Input domain | Output range |
|---|---|---|
| \(\arcsin x\) | \([−1, 1]\) | \([−90°, 90°]\) (\([−\pi/2, \pi/2]\)) |
| \(\arccos x\) | \([−1, 1]\) | \([0°, 180°]\) (\([0, \pi]\)) |
| \(\arctan x\) | all real | \((−90°, 90°)\) (\((−\pi/2, \pi/2)\)) |
There are always infinitely many coterminal solutions; code returns the principal one. Add \(360°k\) (or use symmetry) for others.
import math
print(math.degrees(math.asin(0.5))) # 30.0
print(math.degrees(math.acos(0.5))) # 60.0
print(math.degrees(math.atan(1.0))) # 45.0The atan2 upgrade (read this!)
atan(y/x) loses quadrant information: \((x, y) = (1, 1)\) and \((−1, −1)\) both give ratio 1. atan2(y, x) takes the signs separately and returns the correct angle in \((−\pi, \pi]\).
$$
\text{atan2}(y, x) = \text{angle of point } (x, y) \text{ from the +x axis}
$$
import math
print(math.degrees(math.atan(1))) # 45.0 — fine here
print(math.degrees(math.atan2(1, 1))) # 45.0
print(math.degrees(math.atan2(-1, -1))) # -135.0 (correct quadrant III)
# math.atan(-1/-1) would wrongly say 45 degrees!console.log(Math.atan2(1, 1) * 180 / Math.PI); // 45
console.log(Math.atan2(-1, -1) * 180 / Math.PI); // -135 (correct)
console.log(Math.atan2(0, -1) * 180 / Math.PI); // 180
Rules of thumb:
- Angle of a vector / direction to a target: always
atan2(dy, dx). Neveratan(dy/dx). - Convert \((−180°, 180°]\) output to \([0°, 360°)\) with
% 360if you need compass-style angles. - Argument order is (y, x) — the most common bug is swapping them.
// Aim from (x1, y1) at (x2, y2), screen coords (y down):
function angleTo(x1, y1, x2, y2) {
return Math.atan2(y2 - y1, x2 - x1); // radians
}Common patterns
import math
# Angle from adjacent/hypotenuse etc. — pick the matching inverse:
theta = math.asin(4 / 5) # opposite/hypotenuse
theta = math.acos(3 / 5) # adjacent/hypotenuse
theta = math.atan(4 / 3) # opposite/adjacent (QI/QIV only)
theta = math.atan2(4, 3) # preferred: full-circle safe
# Clamp before asin/acos — floats like 1.0000000002 must not crash:
def safe_acos(x): return math.acos(max(-1.0, min(1.0, x)))
def safe_asin(x): return math.asin(max(-1.0, min(1.0, x)))Practice
- Compute \(\arcsin(1)\), \(\arccos(0)\), \(\arctan(√3)\) by hand (degrees), then verify in code.
- Explain why
asin(2)raises / returns NaN. What does the domain restriction mean geometrically? - Points A(0,0), B(−3, 3). Compute the direction with
atan2and withatan. Which is right, and why? - Write
compass_bearing(dx, dy)returning degrees in \([0, 360)\) measured clockwise from north (hint:atan2(dx, dy), not(dy, dx)).
Next: Trigonometry in Code — putting it all together in real programs.