Number
You can specify integers in binary and octal notation:
> 0xFF // ES5 - hexadecimal
255
> 0b11 // ES6 - binary
3
> 0o10 // ES6 - octal
8
Number.prototype.toString(radix) can be used to convert numbers from decimal.
> 255.toString(16)
'ff'
> 4.toString(2)
'100'
> 8.toString(8)
'10'
For parseInt(string, radix?), if radix is missing, 0, or 16, parseInt parses hexadecimal literal notation to base 10.
> parseInt('0xFF')
255
> parseInt('0xFF', 0)
255
> parseInt('0xFF', 16)
255
Otherwise, digits are parsed until the first non-digit.
> parseInt('0xFF', 10)
0
> parseInt('0xFF', 17)
0
parseInt does not have support for binary or octal literal notation. Number() does, though.
> Number('0b111')
7
> Number('0o10')
8
To parseInt() base 2 or 8 numbers, indicate the radix as the second parameter.
The Number() constructor has new methods in ES6: isFinite, isNaN, parseFloat() and parseInt().
> Number.isFinite(NaN)
false
The constructor method does not automatically coerce its parameter automatically to type 'number,' unlike the global method.
> Number.isFinite('123')
false
> isFinite('123')
true
> Number.isNaN('???')
false
> isNaN('???')
true
NaN is the only value that doesn't equal itself.
> const x = NaN
> x === NaN
false
You can check if a value is NaN using:
> x !== x
true
Using Number.isNaN is more descriptive:
> Number.isNaN(x)
true
Number.parseFloat(string) and Number.parseInt(string, radix) work exactly like their global counterparts.
Rounding errors can become a problem in JavaScript. Number.EPSILON specifies a reasonable margin of error when comparing floating point numbers.
> 0.1 + 0.2 === 0.3
false
> function epsEqu(x, y) { return Math.abs(x - y) < Number.EPSILON; }
> console.log(epsEqu(0.1+0.2, 0.3));
true
JavaScript only has floating point numbers (doubles). Integers are just floating point numbers without a decimal fraction.
Number.isInteger(number) returns true if its parameter is a 'number' and does not have a decimal fraction.
> Number.isInteger(-17)
true
> Number.isInteger(33)
true
> Number.isInteger(33.1)
false
> Number.isInteger('33')
false
> Number.isInteger(NaN)
false
> Number.isInteger(Infinity)
false
JavaScript numbers only have enough storage space to represent 53 bit signed integers. That is, for all integers i in the range -2^53 < i < 2^53 are safe. The following methods determine if an integer is safe:
Number.MAX_SAFE_INTEGER = Math.pow(2, 53)-1;
Number.MIN_SAFE_INTEGER = -Number.MAX_SAFE_INTEGER;
Number.isSafeInteger(number)
JavaScript Safe integers have a one-to-one mapping between them and the mathematical integers they represent. Unsafe integers do not:
> Math.pow(2, 53)
9007199254740992
> 9007199254740992
9007199254740992
> 9007199254740993
9007199254740992
> 9007199254740994
9007199254740994
> 9007199254740995
9007199254740996
> 9007199254740996
9007199254740996
> 9007199254740997
9007199254740996
When performing arithmetic in JavaScript,
isSafeInteger(a) && isSafeInteger(b) && isSafeInteger(a op b)
validates that the result of the operation and its operands are safe integers.
JavaScript's 53-bit integers are a problem if 64-bit integers are needed. The only way around this is to use a library for higher-precision numbers (bigints or bigfloats). Decimal.js is an example library.
Math
Math.sign(x) returns the sign of x as +1 or -1. For 0 and NaN, the parameter is returned.
Math.trunc(x) removes the decimal fraction of x.
Math.cbrt(x) returns the cube root of x.
A good case practice for floating point number is to store them using a 0 instead of a 1. This is because floating point numbers with base 10 are internally represented as mantissa x 10^exponent. Use cases include exponentiation and logarithms.
(A) 0.000000234 = 2.34 * 10-7. Significant digits: 234
(B) 1.000000234 = 1.000000234 * 100. Significant digits: 1000000234
In this example, A has higher precision than B. We can see this applied in the following example:
> 1e-16 === 0
false
> 1 + 1e-16 === 1
true
Math.expml(x) returns Math.exp(x) - 1. This is the inverse of Math.loglp().
This method provides higher precision when Math.exp() has results close to 1. For example:
> Math.expm1(1e-10)
1.00000000005e-10
> Math.exp(1e-10)-1
1.000000082740371e-10
Math.loglp(x) returns Math.log(1 + x).
This method also lets you specify parameters that are close to 1 with higher precision.
> Math.log(1 + 1e-16)
0
> Math.log(1 + 0)
0
In contrast, log1p() produces different results:
> Math.log1p(1e-16)
1e-16
> Math.log1p(0)
0
Math.log2(x) computes the logarithm to base 2.
> Math.log2(8)
3
Math.log10(x) computes the logarithm to base 10.
> Math.log10(100)
2
Trigonometric functions include:
Math.sinh(x)
Math.cosh(x)
Math.tanh(x)
Math.asinh(x)
Math.acosh(x)
Math.atanh(x)
Math.hypot(...values) computes the square root of the sum of the squares of its arguments.
Fun facts: Bitwise operations
Math.clz32(x) counts the leading zero bits in the 32-bit integer x.
> Math.clz32(0b01000000000000000000000000000000)
1
> Math.clz32(0b00100000000000000000000000000000)
2
> Math.clz32(2)
30
> Math.clz32(1)
31
Counting leading zeros in an integer number is a critical operation in many DSP algorithms, such as normalization of samples in sound or video processing, as well as in real-time schedulers to quickly find the highest-priority task ready-to-run.
Source: Exploring ES6 by Dr. Axel Rauschmayer.