JavaScriptArithmetic Operators

Arithmetic Operators

JavaScript supports the arithmetic you'd expect — add, subtract, multiply, divide — plus a few that come up less often: modulo, exponentiation, and the increment/decrement shortcuts. The mechanics are simple; the interesting parts are the edge cases around NaN, Infinity and the special behaviour of + with strings.

The six basic operators

JS
10 + 4;    // 14   addition
10 - 4;    // 6    subtraction
10 * 4;    // 40   multiplication
10 / 4;    // 2.5  division (always float — no integer division)
10 % 4;    // 2    remainder (modulo)
2 ** 10;   // 1024 exponentiation (ES2016)

/ always produces a float. If you want integer division, drop the fractional part explicitly:

JS
Math.trunc(10 / 4);  // 2  (drop toward zero)
Math.floor(10 / 4);  // 2
Math.floor(-10 / 4); // -3 (round down — different from trunc for negatives)
(10 / 4) | 0;        // 2  (bitwise trick — 32-bit only)
Unary plus and unary minus

Used in front of a single operand. - negates; + converts to a number. Unary + is one of the shortest ways to parse a numeric string.

JS
-7;          // -7
-(3 - 1);    // -2

+"42";       // 42   (string → number)
+"42.5";     // 42.5
+"";         // 0    (!)
+"abc";      // NaN
+true;       // 1
+false;      // 0
+null;       // 0
+undefined;  // NaN
Increment and decrement

++ adds 1 to a variable, -- subtracts 1. They come in prefix and postfix flavours that differ in what the expression evaluates to.

JS
let a = 5;
let b = a++;   // postfix: a becomes 6, b gets the OLD value 5

let c = 5;
let d = ++c;   // prefix:  c becomes 6, d gets the NEW value 6

console.log(a, b, c, d);
6 5 6 6

If you use ++ or -- purely for the side effect (a statement on its own line), the prefix/postfix choice doesn't matter. Inside a larger expression — arr[i++], while (--n > 0) — the difference is meaningful and can be confusing. Many style guides discourage mixing ++/-- with other operators on the same line.

Prefer +=
`x += 1` is a hair longer than `x++` but never surprises anyone. It also extends naturally to `x += step`. Some teams ban `++`/`--` outright. Whichever you pick, be consistent.
The + operator and strings

+ is overloaded. If either operand is a string, both are converted to strings and concatenated. Otherwise, both are converted to numbers and added.

JS
1 + 2;             // 3
"1" + 2;           // "12"
1 + "2";           // "12"
1 + 2 + "3";       // "33" — left-to-right: (1+2) is 3, then 3+"3" is "33"
"1" + 2 + 3;       // "123" — string sticks
"" + 42;           // "42"  (tersest way to stringify a number)
A common bug
User input from `<input type="number">` is **still a string** when you read `.value`. `a + b` will concatenate, not add. Convert first: `Number(a) + Number(b)` or `+a + +b`.
NaN — Not a Number

NaN is a special number value that means "this calculation didn't produce a real number". It is contagious: any arithmetic that touches NaN returns NaN.

JS
0 / 0;             // NaN
Math.sqrt(-1);     // NaN
Number("oops");    // NaN
NaN + 1;           // NaN
NaN === NaN;       // false  (!)
Number.isNaN(NaN); // true   — the safe test
Number.isNaN("oops"); // false — Number.isNaN only matches actual NaN

Use Number.isNaN(x) to test, not the older global isNaN(x). The global version coerces to a number first, so isNaN("oops") is true — usually not what you want.

Infinity

Numbers too big to represent become Infinity (or -Infinity). You can also produce Infinity deliberately.

JS
1 / 0;              // Infinity
-1 / 0;             // -Infinity
Infinity + 1;       // Infinity
Infinity - Infinity;// NaN
1e308 * 10;         // Infinity (overflow)

Number.isFinite(42);       // true
Number.isFinite(Infinity); // false
Number.isFinite(NaN);      // false
Floating-point reality

Numbers are 64-bit floats (IEEE 754). Some apparently simple decimals can't be represented exactly.

JS
0.1 + 0.2;             // 0.30000000000000004
0.1 + 0.2 === 0.3;     // false  (!)

// Compare with a tolerance instead
Math.abs((0.1 + 0.2) - 0.3) < 1e-9; // true

// Or round for display
(0.1 + 0.2).toFixed(1); // "0.3"
Why money should be integers
Storing prices in cents (`1999` for $19.99) rather than dollars-as-floats (`19.99`) sidesteps the whole floating-point question. Convert to display strings only at the edges.
Modulo and negative numbers

% returns a value with the sign of the dividend (the left operand). This trips up anyone coming from a language with a true mathematical modulo.

JS
10 % 3;    // 1
-10 % 3;   // -1   (sign of -10)
10 % -3;   // 1
-10 % -3;  // -1

// A "positive modulo" helper
const mod = (n, m) => ((n % m) + m) % m;
mod(-10, 3); // 2
Exponentiation

JS
2 ** 8;      // 256
2 ** 0.5;    // 1.4142135... (square root)
(-2) ** 3;   // -8
// -2 ** 3;  // SyntaxError — must parenthesise a unary minus on the left of **
Math.pow(2, 8); // 256 — older form, identical result
Numeric separators

Underscores can be used in numeric literals to make long numbers readable. The engine ignores them.

JS
const billion = 1_000_000_000;
const mac      = 0xff_ee_dd_cc_bb_aa;
const binary   = 0b1010_0110_1110_0001;
BigInt arithmetic

For integers beyond Number.MAX_SAFE_INTEGER, use BigInt. It supports the same operators, but you can't mix bigint and number in the same expression.

JS
9_007_199_254_740_993n + 1n;   // 9007199254740994n
2n ** 64n;                     // 18446744073709551616n
// 1n + 1;                     // TypeError — mixed types
Number(2n ** 32n);             // 4294967296 (back to a regular number, if it fits)
Stay in numbers as long as you can
If you're doing math, do all of it before converting to a string. Mixing string concatenation and math in the same expression is a recipe for unintended `"234"` instead of `9`.