This is a work in progress. All code examples have been run on Node 8.11.5
IEEE 754) for all arithmetics.
The IEEE 754 can only represent safely numbers between
-(253 - 1) and
253 - 1.
Quoting the Wikipedia:
An IEEE 754 format is a "set of representations of numerical values and symbols". A format may also include how the set is encoded.
Quoting again the Wikipedia:
Floating point is used to represent fractional values, or when a wider range is needed than is provided by fixed point (of the same bit width), even if at the cost of precision.
Some numbers can't be exactly represented with binary numbers in the computer, that causes things like this to happen:
Integers (without decimal point or exponent notation) are accurate up to 15 digits, beyond this not all integer numbers can be represented accurately.
We have two types of zero (signed zero), negative and positive;
We'll see in the section for
Infinity how this results when doing a division by zero.
We can check for negative zero using division and a comparison to zero itself, taking advantage of positive/negative
If we try to convert negative or positive zero to a string we just get a '0':
Also if we try to search for negative/positive zero in arrays, since
=== we get the position
of either positive or negative:
Same for conditional operators (ordering):
Number is a wrapper object, used like this:
When the argument can't be converted to number it returns
NaN. NaN is a value representing "Not a number".
A number created with the
Number constructor gives us an object:
This means we can't compare it with other numbers, since they are different types:
We can get the value using
When using the
== comparison operator we do get the expected result (since this is not type strict):
If we use two
Number objects we can't compare them this way:
To avoid this kind of issues we most of the times don't use wrapped Number objects, instead just use numbers.
Number is a function:
new keyword (non-constructor context),
Number performs a type conversion.
true is converted to 1, and
false to 0:
undefined is converted into
null is converted into zero:
Strings are parsed when possible, ignoring trailing and leading whitespace. Empty string is converted to zero.
For this, whitespace includes new lines, tabs, etc. For example:
Empty list is converted to zero:
If a list contains one item that is possible to convert to a number we get that number:
If our list has more than one item, or it is not possible to convert the first item into a number, we get NaN:
Empty objects and functions return NaN:
The reason behind all this is because of the process used to convert the parameter passed to
In this case we have a valueOf:
In this case we are using the
In the case of passing a date to Number, we get the milliseconds since midnight January 1, 1970 UTC,
value that is returned by the
valueOf method of the date instance,
and also the method
When joining a number with a string, you might get something unexpected:
With subtraction tho, it converts the string into a number and then does the subtraction:
Since an empty list is converted into zero, if we add to an empty list we get something like this:
We have then to be careful what we are adding when using addition, we might get unexpected things.
In this case the
["2"] is causing all of our operation to be treated as a string concatenation.
Numbers can be written in different formats, like Hexadecimal (base 16) starting with
Octal (base 8) format starting with a leading
Octal can also be written with a leading
Binary (base 2) format starting with a leading
Using the short e-notation. This notation indicates a number that should be multiplied by 10 raised to a
a power. For example,
1e9 is one billion:
The e-notation can have negative numbers too:
Different formats are just for representation and can be used with other formats:
NaN is a value representing "Not a number". This function gives answer to the question: "Is this value, when coerced to a number, an IEEE-754 'NaN' value?". You can read more on NaN for floating point in Wikipedia.
NaN is usually returned when
Math functions fail:
isNaN checks if a value is NaN or not. This is useful since we can't rely on the
=== operators to check against NaN. NaN is never equal to itself.
When called without a parameter (it is undefined) we get
And of course NaN is a NaN:
Since NaN is never equal to NaN, we can't search for it in arrays:
NaN values are generated when arithmetic operations give us undefined or something that can't be represented as a number.
When we divide zero by itself, we get a NaN, this is because NaN is not the same as infinity, as we will see when we divide other numbers by zero.
As we will see later ECMAScript 2015 added the
isNaN method to Number instances.
Another way to check if a number is NaN is checking it against itself, taking advantage of the unique "never equal to itself" feature of NaN.
When used in arithmetic operations everything is NaN:
Infinity is a read-only global value that represent infinity. The initial value of Infinity is
Infinity is a number type:
When we divide a number by zero, we get Infinity:
If we do a negative zero division we get a negative Infinity, and with positive zero we get a positive Infinity:
Also in the case when we use
Math.pow with zero and a negative number:
If we multiply any number by Infinity we get Infinity:
If we subtract Infinity to a number we get a negative Infinity:
If you try to do a subtraction of Infinity to Infinity, you get NaN. Same for division:
Trying to add to infinity or to multiply will never give you anything different;
Number.isNaN(). This one is different than the global
isNaN function, since this one does not convert
the parameter to a number. This makes it safer to test against actual NaN, only values of type number that are NaN return true.
Number.isFinite(). This one is also different to the global version of
isFinite since it does not
convert the parameter to a number. Only values of type number that are finite return true.
Number.parseFloat(). Parses the argument and returns a floating point number, if it can't convert it to float, it returns
Number.parseInt(). Takes 2 parameters, first one is a string, if it is not a string it is converted to one (using
The second one is the
radix, usually the default is 10, but might change on implementations.
Always set the radix to avoid confusion.
Number.prototype.toExponential(). Receives an option parameter to specify the number of digits after the decimal point. Returns a string, and
RangeError if the parameter is too big/small, or
TypeError if invoked in something that is not a number.
Number.prototype.toFixed(). Receives a parameter of the number of decimal points to show (between 0 and 20)
and returns a string with the specified decimal points. The number is rounded if necessary, and the fractional part padded with zeros for
the desired length.
Number.prototype.toLocaleString(). Returns a string with a language sensitive representation of the number. Accepts two parameters
locales (string with a BCP 47 language tag, like "hi"). And the second parameter an object with options localeMatcher, style, currency,
currencyDisplay, useGrouping, minimumIntegerDigits, minimumFractionDigits, maximumFractionDigits, minimumSignificantDigits and
Number.prototype.toPrecision(). Returns a string representing a Number object in fixed-point/exponential
notation, rounded if necessary, and the fractional part padded with zeros for the desired length.
Number.prototype.toString(). Returns a string representing the number. Accepts a parameter
between 2 to 36 for the base to use.
Number.prototype.valueOf(). Returns the primitive value of a number object.
If we try to compare this with
0.3 we get this:
Quoting the WikiBooks:
When a real number is rounded to the nearest floating point number, the machine epsilon forms an upper bound on the relative error.
Basically, we can use the upper bound to compare our values:
Made with by PR