In JavaScript, which operations produce Infinity and which produce NaN? Explain the rules with examples.
answer
- range errors saturate instead of throwing
- division by zero has a sign
- 0/0 has no defensible answer
- typeof Infinity is "number"
- Math.max() returns the identity element
basics
~10 sA nonzero number divided by zero, or arithmetic that overflows the double range, gives a signed Infinity. Genuinely indeterminate forms give NaN: 0/0, Infinity - Infinity, Infinity * 0, Infinity / Infinity. Neither throws.
solid answer
~50 sJavaScript numbers are IEEE-754 doubles, and the standard says overflow saturates rather than throws. So `1/0` is `Infinity`, `-1/0` is `-Infinity`, and any result too large to represent — `Number.MAX_VALUE * 2`, or the literal `1e309` — becomes a signed `Infinity`. Underflow goes the other way, collapsing to `0` or `-0`. NaN is reserved for the indeterminate forms, where no signed infinity or finite value is the right answer: `0/0`, `Infinity - Infinity`, `Infinity * 0`, `Infinity / Infinity`, and `Math.sqrt(-1)`. Both are ordinary Number values — `typeof Infinity` is `"number"` — and neither raises an exception, which is why bad arithmetic surfaces far from its cause. `Number.isFinite(x)` is the guard that rejects NaN and both infinities at once. `Math.max()` with no arguments returns `-Infinity` and `Math.min()` returns `Infinity`, since those are the identity values for the two operations.
code
javascript · 11 linesconsole.log(1 / 0, -1 / 0); // Infinity -Infinity
console.log(0 / 0); // NaN — indeterminate
console.log(Infinity - Infinity, Infinity * 0); // NaN NaN
console.log(Number.MAX_VALUE * 2); // Infinity (overflow)
console.log(-1e-400); // -0 (underflow)
console.log(Math.max(), Math.min()); // -Infinity Infinity
console.log(Math.max(...[])); // -Infinity
console.log(typeof Infinity); // "number"
console.log(Number.isFinite(Infinity)); // falsego deeper
Know that 1/0 is Infinity and 0/0 is NaN, that neither throws, and that typeof Infinity is "number". Recognising both values in output is the baseline.
Explain saturation versus indeterminate forms: overflow and division by a nonzero numerator give a signed infinity, while 0/0, Infinity - Infinity and Infinity * 0 give NaN.
Show where you place a Number.isFinite guard so an overflow is caught at its source, and describe how a non-finite value degrades once it reaches formatting or serialization.
Own the policy for non-finite results across service boundaries: whether they are rejected, clamped, or represented explicitly, and how the choice keeps a silent overflow from becoming an unexplained null downstream.
## Saturation, not exceptions IEEE-754 defines what happens when a floating-point result cannot be represented, and JavaScript adopts it wholesale: arithmetic never throws for a numeric range problem. Overflow saturates to a signed infinity, underflow collapses to a signed zero, and operations with no defensible answer produce NaN. Nothing in that chain raises an exception, so the failure travels silently into whatever consumes the result. ```js Number.MAX_VALUE * 2; // Infinity 1e309; // Infinity — even the literal overflows -1e309; // -Infinity 1e-400; // 0 — underflow -1e-400; // -0 — underflow keeps the sign ``` ## Division by zero Dividing a nonzero finite number by zero gives an infinity whose sign is the combined sign of the operands: ```js 1 / 0; // Infinity -1 / 0; // -Infinity 1 / -0; // -Infinity -1 / -0; // Infinity ``` This is the point most often mis-remembered by people arriving from languages where integer division by zero throws. In JavaScript there is only one numeric type here and only one behaviour: a signed infinity. ## The indeterminate forms NaN appears when the mathematical answer is genuinely undetermined — where you cannot pick either a finite value or a signed infinity without lying: ```js 0 / 0; // NaN Infinity - Infinity; // NaN Infinity * 0; // NaN Infinity / Infinity; // NaN Math.sqrt(-1); // NaN Infinity % 2; // NaN ``` Contrast `1/0` (a definite magnitude direction: unbounded, positive) with `0/0` (any value could be argued for). That distinction is the rule worth carrying: **a definite direction gives an infinity; no defensible answer gives NaN.** ## Infinity as a value you can use `Infinity` is a global property, non-writable and non-configurable since ES5, and `Number.POSITIVE_INFINITY` / `Number.NEGATIVE_INFINITY` name the same values. `typeof Infinity` is `"number"`, and it compares as you would hope: `Infinity > Number.MAX_VALUE` is true, and `-Infinity` is below every finite number. That makes the infinities useful as sentinels: ```js let best = Infinity; for (const item of items) { if (item.cost < best) best = item.cost; } ``` The same reasoning explains the spec's odd-looking defaults: `Math.max()` with no arguments returns `-Infinity` and `Math.min()` returns `Infinity`, because those are the identity elements — anything you subsequently compare against them wins. That behaviour also means `Math.max(...arr)` on an **empty** array yields `-Infinity` rather than throwing, which is a real source of "where did -Infinity come from?" bugs in aggregation code. ## Detecting and guarding `Number.isFinite(x)` is true only for a Number that is neither NaN nor an infinity, so it is the single guard that covers all three problem values. `Number.isNaN(x)` is not enough on its own: an overflowed computation is `Infinity`, which is not NaN and would pass that check. ```js function safeRate(distance, seconds) { const rate = distance / seconds; return Number.isFinite(rate) ? rate : null; } safeRate(10, 0); // null — was Infinity ``` The global `isFinite` exists too, but it converts its argument first (`isFinite("100")` is true), so prefer the `Number.` method. ## Where infinities cause trouble downstream An `Infinity` that escapes a computation tends to surface far away and in a confusing shape. It renders as the string `"Infinity"`, which fails most numeric parsers on the receiving side. It also does not survive JSON: `JSON.stringify` writes non-finite numbers as `null`, so an `Infinity` sent over the wire silently arrives as `null` and the original overflow is unrecoverable. And an infinity that later participates in a subtraction or a multiplication by zero degrades into NaN, at which point even the sign is gone. The defensive habit is the same as for NaN: check with `Number.isFinite` at the boundary where a computed number leaves its module, so the value is rejected while you still know which computation produced it.
- Why does 1/0 give Infinity while 0/0 gives NaN?IEEE-754 distinguishes a result with a definite direction from one with none. As the divisor approaches zero with a nonzero numerator, the magnitude grows without bound and the sign is determined, so a signed infinity is the honest answer. With a zero numerator no value is more defensible than any other, so the standard returns NaN rather than inventing one.
- An aggregation reports -Infinity as its maximum. What is the likely cause?`Math.max()` called with no arguments — usually `Math.max(...values)` on an empty array — returns `-Infinity`, because that is the identity element for maximum. Nothing threw, so the sentinel flowed straight into the report. Guard the empty case explicitly, or reduce with an explicit initial value that your domain can defend.
- What happens to Infinity when the value is serialized to JSON?`JSON.stringify` has no representation for non-finite numbers, so `Infinity`, `-Infinity` and NaN are all written as `null`. The overflow becomes indistinguishable from a genuinely absent value on the receiving side. If a non-finite result is meaningful, encode it explicitly as a string or a status field rather than letting it pass silently.
saying these in an interview costs you the question
- Expects division by zero to throw an error
- Says 1/0 is NaN, conflating overflow with indeterminate forms
- Thinks Infinity is a special type rather than a number
- Guards only against NaN and lets Infinity through
- Surprised that Math.max() with no arguments returns -Infinity