Math.sin()
Returns the sine of an angle given in radians, a value between -1 and 1.
Math.sin(x)- Added in JavaScript ES1
Parameters
| Parameter | Type | Description |
|---|---|---|
$x | number | A number representing an angle in radians. |
Return value
numberThe sine of x, between -1 and 1, inclusive. If x is Infinity, -Infinity, or NaN, returns NaN.
Math.sin(x) takes an angle in radians and returns its sine. A full turn is 2 * Math.PI radians, so degrees must be converted first: deg * Math.PI / 180. Passing degrees directly is the number one bug on this function, and it fails silently — Math.sin(90) is 0.894, not 1.
When to reach for it
Paired with Math.cos() it converts polar coordinates to Cartesian: a point at angle θ and radius r sits at (r*cos θ, r*sin θ). On its own it is the standard oscillator — smooth easing, bobbing and pulsing animations, audio tones, and any periodic signal are built from Math.sin(2 * Math.PI * frequency * t).
What trips people up
Exact zeros do not survive floating point. Math.sin(Math.PI) is 1.2246467991473532e-16, not 0, because Math.PI is itself a rounded approximation of π. Never compare a sine result with ===; test against a small epsilon instead.
Non-finite input gives NaN, since an infinite angle has no defined position on the circle. Very large angles stay finite but lose precision, as the argument reduction has fewer significant bits to work with — keep accumulating phase values wrapped into [0, 2π).
Example
When to use it
- Drive a smooth looping animation such as a bobbing or pulsing element
- Plot points on a circle from an angle and radius
- Generate a sine-wave tone or a periodic test signal
- Compute the vertical component of a vector given its angle
Frequently asked questions
Does Math.sin() take degrees or radians?
Math.sin() takes radians. Convert degrees first with degrees * Math.PI / 180 — Math.sin(90) treats 90 as radians and returns 0.894, while Math.sin(90 * Math.PI / 180) correctly returns 1.
Why does Math.sin(Math.PI) not return 0?
Math.PI is a double approximation of π, so the argument is very slightly off from the true π and the sine of that near-π value is about 1.22e-16. Compare trigonometric results against a small epsilon rather than using strict equality.
How do I animate something smoothly with Math.sin()?
Feed elapsed time into Math.sin(2 * Math.PI * frequency * seconds) and multiply the result by the amplitude you want. The output sweeps smoothly between -amplitude and +amplitude and repeats every 1/frequency seconds.
More examples
Points on a circle
Four evenly spaced angles produce (10,0), (0,10), (-10,0) and (0,-10). Rounding to three decimals hides the 1e-15 residue that Math.sin() and Math.cos() leave at the quarter turns.
function circlePoints(count, radius) {
return Array.from({ length: count }, (_, i) => {
const angle = (i / count) * 2 * Math.PI;
return {
x: +(radius * Math.cos(angle)).toFixed(3),
y: +(radius * Math.sin(angle)).toFixed(3),
};
});
}
console.log(circlePoints(4, 10));An oscillator over time
At 2 Hz the value completes a full cycle every 500 ms, peaking at +50 after 125 ms and reaching -50 at 375 ms. The 2π factor converts cycles into radians, which is what Math.sin() expects.
const frequency = 2; // cycles per second
const amplitude = 50; // pixels
for (let ms = 0; ms <= 500; ms += 125) {
const t = ms / 1000;
const offset = amplitude * Math.sin(2 * Math.PI * frequency * t);
console.log(ms + "ms", offset.toFixed(2));
}Comparing results safely
Strict equality against 0 fails at π because Math.PI is only an approximation; the epsilon comparison passes. Infinity yields NaN, and negative zero is preserved through the call.
const nearly = (a, b, eps = 1e-12) => Math.abs(a - b) < eps;
console.log(Math.sin(Math.PI) === 0);
console.log(nearly(Math.sin(Math.PI), 0));
console.log(Math.sin(Math.PI / 2) === 1); // this one happens to hold
console.log(Math.sin(Infinity));
console.log(Math.sin(-0)); // signed zero preserved
Discussion