# New Number and Math Features in ES6

#### 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.

Published March 14, 2016