Katkat

Explain JavaScript Numeric Edge Cases

RiotgamesSoftware Engineer · Technical Screen

Last updated

This question tests your understanding of IEEE 754 floating-point representation in JavaScript, specifically how the language handles non-numeric values, precision limits, and type safety.

Challenge: JavaScript Numeric Safety

In JavaScript, all numbers are 64-bit floats. This design leads to unique behaviors when dealing with values that fall outside the range of typical integers or valid numbers.

Implement the following three utility functions to handle these specific edge cases:

  1. isTrulyNumeric(val): Returns true if the input is a finite, valid number that is not NaN or Infinity. Ensure it correctly handles numeric strings that can be parsed as valid numbers.
  2. isSafeInteger(val): Returns true only if the value is an integer within the range Number.MIN_SAFE_INTEGER to Number.MAX_SAFE_INTEGER.
  3. safeAdd(a, b): Returns the sum of a and b if the result is a safe integer; otherwise, return a custom error message string: "Result exceeds safe integer limits".

Examples

isTrulyNumeric(10); // true
isTrulyNumeric("12.5"); // true
isTrulyNumeric(NaN); // false
isTrulyNumeric(Infinity); // false

isSafeInteger(Math.pow(2, 53) - 1); // true
isSafeInteger(Math.pow(2, 53)); // false

safeAdd(5, 10); // 15
safeAdd(Number.MAX_SAFE_INTEGER, 1); // "Result exceeds safe integer limits"

Constraints

  • Do not use Number.isSafeInteger() or Number.isFinite() directly in your implementation; rely on basic mathematical operators or standard properties to demonstrate understanding.
  • Your functions should handle edge cases like null, undefined, and boolean inputs gracefully (treating them as non-numeric).

Hints

Hint 1

Recall that `typeof NaN` is 'number', so checking `typeof val === 'number'` is insufficient to exclude all non-numeric values.

Hint 2

The range of safe integers is defined by `2^53 - 1` due to the limits of the mantissa in IEEE 754 precision.

Hint 3

Consider how the unary plus operator `+val` or `Number(val)` treats strings compared to how `parseFloat` treats them.

Follow-up questions

  • How does JavaScript's `Number.MAX_SAFE_INTEGER` differ from `Number.MAX_VALUE`?
  • Why might you choose `BigInt` over standard `Number` types when building a financial application?
  • Can you explain the behavior of `0.1 + 0.2 === 0.3` in JavaScript and how you would mitigate this for currency calculations?