Numbers
There are basically two types of numbers in JavaScript:
- Regular numbers: These are double-precision floating-point numbers stored in 64-bit format IEEE-754. The double-precision floating-point numbers are responsible for things like imprecise calculation.
0.2 + 0.1 // 0.30000000000000004
// caused by double-precision floating-point (64 bit)
These numbers are between -2⁵³ - 1 (minimum safe integer) and 2⁵³ - 1 (maximum safe integer).
Number.MIN_SAFE_INTEGER // -9007199254740991 (-2⁵³ - 1)
Number.MAX_SAFE_INTEGER // 9007199254740991 (2⁵³ - 1)
- BigInt numbers: These are numbers below -2⁵³ - 1 or above 2⁵³ - 1 (B ≤ -2⁵³ - 1 or B ≥ 2⁵³ - 1)
Numbers in underscore
Digits can be separated with underscores. For example, 18,054,020 can be represented as 18_054_020
in JavaScript.
Numbers in exponential
Let's assume we want to represent the number 2,000,000,000 in exponential. In Maths, it's 2x10⁹. In JavaScript, it's 2e9
or 2E9
.
See the examples below:
2e9 === 2000000000; // true
1e-3 === 1 / 1000; // true
1.43e-6 === 1.43 / 1000000; // true
In the example above, 2e-9
is the same as 0.000000002 (9 zeros to the left).
Hex, binary and octal numbers
Hexadecimal numbers
Hexadecimal can be used to represent colors, encode characters, etc.
Normally one or two characters (aA-fF or numbers 0 - 9) appends to 0x
.
See the example below:
0x4a; // 74
0xf9; // 249
console.log(`Hexadecimal numbers are between ${0x00} and ${0xff}.`)
// Hexadecimal numbers are between 0 and 255.
Binary and octal numbers
The prefix 0b
represents a binary number while the prefix 0o
represents an octal number.
See the example below:
const a = 0b11111111; // binary form of 255
const b = 0o377; // octal form of 255
console.log( a === b ); // true
toString(base)
To convert a whole num
to base a
the syntax is:
num.toString(a)
See the example below:
const num = 255;
num.toString(16); // ff
num.toString(2); // 11111111
The base can vary from
2
to36
. By default, it's10
.
Note: If you do not want to use the variable (num
) to store a number but want to call a method directly on a number, the ..
can be used.
The example above is the same as below:
255..toString(16); // ff
255..toString(2); // 11111111
Alternative to the example above, it can be rewritten as shown below:
(255).toString(16); // ff
(255).toString(2); // 11111111
Rounding
There are several built-in functions for rounding:
Math.floor(num)
andMath.round(num)
: They round down numbers to the nearest whole number.3.24
becomes3
.
The difference between Math.floor(num)
and Math.round(num)
is shown in the example below:
console.log( Math.floor(3.4), Math.round(3.4) ) // 3 3
console.log( Math.floor(3.5), Math.round(3.5) ) // 3 4
console.log( Math.floor(3.6), Math.round(3.6) ) // 3 4
For negative decimal numbers (-num
), Math.floor(-num)
becomes -Math.abs(num + 1)
to the nearest whole number; while Math.round(-num)
becomes -Math.abs(num)
to the nearest whole number.
See the example below:
console.log( Math.floor(-3.3), Math.round(-3.3) ); // -4 -3
For positive decimal numbers, Math.round(num)
round-up numbers (num
) exactly at or after .5
position but round-down numbers (num
) before .5
position, but Math.floor(num)
always round-down.
Math.ceil(num)
always round up numbers (num
).
Math.ceil(3.4) // 4
Math.ceil(3.2) // 4
Math.ceil(3.6) // 4
Math.trunc(num)
: It is likeMath.floor
for positive numbers but likeMath.round(num)
for negative numbers.
See the example below:
Math.trunc(3.4); // 3
Math.trunc(3.5); // 3
Math.trunc(3.6); // 3
Math.trunc(-3.6); // 3
Math.trunc(-3.4); // 3
It is advisable to use math.trunc(num)
more often than Math.floor(num)
to round-down numbers. Math.floor(num)
is mostly used on positive decimal numbers.
number | Math.ceil | Math.floor | Math.round | Math.trunc |
3.1 | 4 | 3 | 3 | 3 |
3.6 | 4 | 3 | 4 | 3 |
-3.1 | -3 | -4 | -3 | -3 |
-3.6 | -3 | -4 | -4 | -3 |
Math.trunc
is not supported by Internet Explorer
Imprecise calculation
A number internally is represented in 64-bit format IEEE-754 - 52 bits to store digits; 11 bits to store decimal numbers position (zero for integer numbers); 1 bit for signs.
console.log(1e550); // Infinity
0.2 + 0.1 === 0.3 // false
// The above is false because
0.2 + 0.1 // 0.30000000000000004
// ☝ the operation on 0.1, 0.2 causes
// unending fractions in their binary form.
the operation on 0.1, 0.2 causes unending fractions in their binary form
To solve the issue, we can use the method num.toFixed(n)
num.toFixed(n)
See the example below:
const num = 0.1 + 0.2;
const result = num.toFixed(1); // 0.3
console.log(result, typeof result); // 0.3 string
console.log(typeof +result) // number
num.toFixed(n)
is in string.
n=1
specifies the number of digits after 0.
toFixed
always returns a string
See the example below
const num = 0.2 + 0.1;
const result = num.toFixed(2);
console.log(result, typeof result); // 0.30 string
To convert the result above to a number, use the unary operator (+
) or Number(...)
const num = 0.2 + 0.1;
const result = num.toFixed(2);
const toNum = +result; // Number(result)
console.log(toNum, typeof toNum); // 0.30 number
Alternatively, you can change the decimal numbers in an expression to fractional numbers and multiply both numerator and denominator by 10.
// const num = ((0.1 * 10) + (0.2 * 10)) / 10;
const num = ((1/10 * 10) + (2/10 * 10)) / 10;
num;
The trick above doesn't always work. This means the formal, num.toFixed(n)
is the preferred way to fix numbers.
0.28 + 0.14; // 0.42000000000000004
// ( (28 / 100 * 100) + (14 / 100 * 100) ) / 100
( (0.28 * 100) + (0.14 * 100) ) / 100 ; // 0.4200000000000001
// num.toFixed(n)
+(0.28 + 0.14).toFixed(2); // 0.42
Integers (non-decimal) numbers are accurate up to 15 digits.
const a = 999999999999999; // 15 9s
const b = 9999999999999999; // 16 9s will lead to wrong interpretation
console.log(a, b); // 999999999999999 10000000000000000
Tests - isFinite and isNaN
isNaN(value)
converts its argument to a number and then tests it for beingNaN
: Non-integer values areNaN
.
See the example below:
console.log( isNaN(NaN) ); // true
console.log( isNaN("str") ); // true
console.log( isNaN(10) ); // false
The value NaN is unique in that it does not equal anything.
NaN === NaN // false
In JavaScript, Object.is(a, b)
is used when an internal algorithm needs to compare two values for being exactly the same.
Object.is(NaN, NaN); // true
Object.is(0, 0); // true
Object.is(0, -0); //false
isFinite(value)
converts its argument to a number and returns true - not eitherNaN
Infinity
or-Infinity
.
See the example below:
console( isFinite("41") ); // true => value number
console( isFinite("str") ); // false => value NaN
console( isFinite(Infinity) ); // false => value Infinity
Sometimes
isFinite(value)
is used to validate whether a string value is a regular number:
const num = +prompt("Enter a number", ' ');
alert( isFinite(num), typeof num);
ParseInt and ParseFloat
- The function
parseInt(...)
returns an integer. - The function
parseFloat(...)
returns a floating-point number.
parseInt(100.45) // 100
parseFloat(100) // 100.00
Both functions only read a number from a string.
parseInt('30$'); // 30
ParseInt base
If a parseInt function has a second argument, the second argument becomes the base to be converted to.
See the syntax below:
parseInt(str[, radix])
parseInt('0xff', 16); // 255
parseInt('ff', 16); // 255, without 0x also works
parseInt('2n9c', 36); // 123456
Built-in Math functions
Check out MDN for other built-in Math functions
Happy coding!