# Numerical expansion

## Binary and octal notation

ES6 provides a new way of writing binary and octal values, which are represented by prefixes `0b` (or `0B`) and `0o` (or `0O`) respectively.

``````0b111110111 === 503; // true
0o767 === 503; // true
``````

Starting from ES5, in strict mode, the prefix `0` is no longer allowed in octal system. ES6 further clarifies that the prefix `0o` should be used.

``````// Non-strict mode
(function () {
console.log(0o11 === 011);
})()(
// true

// strict mode
function () {
"use strict";
console.log(0o11 === 011);
}
)(); // Uncaught SyntaxError: Octal literals are not allowed in strict mode.
``````

If you want to convert the string values ​​prefixed with `0b` and `0o` to decimal, use the `Number` method.

``````Number("0b111"); // 7
Number("0o10"); // 8
``````

## Number.isFinite(), Number.isNaN()

ES6 provides two new methods, `Number.isFinite()` and `Number.isNaN()`, on the `Number` object.

`Number.isFinite()` is used to check whether a value is finite, that is, it is not `Infinity`.

``````Number.isFinite(15); // true
Number.isFinite(0.8); // true
Number.isFinite(NaN); // false
Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false
Number.isFinite("foo"); // false
Number.isFinite("15"); // false
Number.isFinite(true); // false
``````

Note that if the parameter type is not numeric, `Number.isFinite` always returns `false`.

`Number.isNaN()` is used to check whether a value is `NaN`.

``````Number.isNaN(NaN); // true
Number.isNaN(15); // false
Number.isNaN("15"); // false
Number.isNaN(true); // false
Number.isNaN(9 / NaN); // true
Number.isNaN("true" / 0); // true
Number.isNaN("true" / "true"); // true
``````

If the parameter type is not `NaN`, `Number.isNaN` always returns `false`.

The difference between them and the traditional global methods `isFinite()` and `isNaN()` is that the traditional method first calls `Number()` to convert a non-numeric value to a numeric value, and then judges, and these two new methods only Valid for numeric values, `Number.isFinite()` always returns `false` for non-numeric values, `Number.isNaN()` returns `true` only for `NaN`, and always returns `false` for non-`NaN`.

``````isFinite(25); // true
isFinite("25"); // true
Number.isFinite(25); // true
Number.isFinite("25"); // false

isNaN(NaN); // true
isNaN("NaN"); // true
Number.isNaN(NaN); // true
Number.isNaN("NaN"); // false
Number.isNaN(1); // false
``````

## Number.parseInt(), Number.parseFloat()

ES6 transplants the global methods `parseInt()` and `parseFloat()` to the `Number` object, and the behavior remains completely unchanged.

``````// How to write ES5
parseInt("12.34"); // 12
parseFloat("123.45#"); // 123.45

// How to write ES6
Number.parseInt("12.34"); // 12
Number.parseFloat("123.45#"); // 123.45
``````

The purpose of this is to gradually reduce the overall approach and make the language gradually modular.

``````Number.parseInt === parseInt; // true
Number.parseFloat === parseFloat; // true
``````

## Number.isInteger()

`Number.isInteger()` is used to determine whether a number is an integer.

``````Number.isInteger(25); // true
Number.isInteger(25.1); // false
``````

In JavaScript, integers and floating-point numbers use the same storage method, so 25 and 25.0 are considered the same value.

``````Number.isInteger(25); // true
Number.isInteger(25.0); // true
``````

If the parameter is not a number, `Number.isInteger` returns `false`.

``````Number.isInteger(); // false
Number.isInteger(null); // false
Number.isInteger("15"); // false
Number.isInteger(true); // false
``````

Note that since JavaScript adopts the IEEE 754 standard, the value is stored in a 64-bit double-precision format, and the numerical precision can reach up to 53 binary digits (1 hidden bit and 52 effective digits). If the precision of the value exceeds this limit, the 54th and subsequent bits will be discarded. In this case, `Number.isInteger` may be misjudged.

``````Number.isInteger(3.0000000000000002); // true
``````

In the above code, the parameter of `Number.isInteger` is obviously not an integer, but it will return `true`. The reason is that the precision of this decimal has reached 16 decimal digits after the decimal point, and the conversion into binary digits exceeds 53 binary digits, resulting in the last `2` being discarded.

In a similar situation, if the absolute value of a number is less than `Number.MIN_VALUE` (5E-324), that is, less than the minimum value that JavaScript can distinguish, it will be automatically converted to 0. At this time, `Number.isInteger` will also misjudge.

``````Number.isInteger(5e-324); // false
Number.isInteger(5e-325); // true
``````

In the above code, `5E-325` will be automatically converted to 0 because the value is too small, so it returns `true`.

In short, if the data accuracy requirements are high, it is not recommended to use `Number.isInteger()` to determine whether a value is an integer.

## Number.EPSILON

ES6 adds a tiny constant `Number.EPSILON` to the `Number` object. According to the specification, it represents the difference between 1 and the smallest floating-point number greater than 1.

For 64-bit floating-point numbers, the smallest floating-point number greater than 1 is equivalent to the binary `1.00..001`, with 51 consecutive zeros after the decimal point. After subtracting 1 from this value, it is equal to 2 to the -52th power.

``````Number.EPSILON === Math.pow(2, -52);
// true
Number.EPSILON;
// 2.220446049250313e-16
Number.EPSILON.toFixed(20);
// "0.00000000000000022204"
``````

`Number.EPSILON` is actually the smallest precision that JavaScript can represent. If the error is less than this value, it can be considered as meaningless, that is, there is no error.

The purpose of introducing such a small amount is to set an error range for floating-point calculations. We know that floating-point calculations are imprecise.

``````0.1 + 0.2;
// 0.30000000000000004

0.1 + 0.2 - 0.3;
// 5.551115123125783e-17

(5.551115123125783e-17).toFixed(20);
// '0.00000000000000005551'
``````

The above code explains why the result of comparing `0.1 + 0.2` with `0.3` is `false`.

``````0.1 + 0.2 === 0.3; // false
``````

`Number.EPSILON` can be used to set the "acceptable error range". For example, the error range is set to the power of 2-50 (ie `Number.EPSILON * Math.pow(2, 2)`), that is, if the difference between two floating-point numbers is less than this value, we consider these two floating-point numbers equal.

``````5.551115123125783e-17 < Number.EPSILON * Math.pow(2, 2);
// true
``````

Therefore, the essence of `Number.EPSILON` is an acceptable minimum error range.

``````function withinErrorMargin(left, right) {
return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);
}

0.1 + 0.2 === 0.3; // false
withinErrorMargin(0.1 + 0.2, 0.3); // true

1.1 + 1.3 === 2.4; // false
withinErrorMargin(1.1 + 1.3, 2.4); // true
``````

The above code is floating-point arithmetic, and an error checking function is deployed.

## Safe Integer and Number.isSafeInteger()

The integer range that JavaScript can accurately represent is between `-2^53` and `2^53` (excluding the two endpoints). If this range is exceeded, this value cannot be accurately represented.

``````Math.pow(2, 53); // 9007199254740992

9007199254740992; // 9007199254740992
9007199254740993; // 9007199254740992

Math.pow(2, 53) === Math.pow(2, 53) + 1;
// true
``````

In the above code, after exceeding 2 to the 53rd power, a number becomes inaccurate.

ES6 introduced the two constants `Number.MAX_SAFE_INTEGER` and `Number.MIN_SAFE_INTEGER` to indicate the upper and lower limits of this range.

``````Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1;
// true
Number.MAX_SAFE_INTEGER === 9007199254740991;
// true

Number.MIN_SAFE_INTEGER === -Number.MAX_SAFE_INTEGER;
// true
Number.MIN_SAFE_INTEGER === -9007199254740991;
// true
``````

In the above code, you can see the limit that JavaScript can accurately represent.

`Number.isSafeInteger()` is used to determine whether an integer falls within this range.

``````Number.isSafeInteger("a"); // false
Number.isSafeInteger(null); // false
Number.isSafeInteger(NaN); // false
Number.isSafeInteger(Infinity); // false
Number.isSafeInteger(-Infinity); // false

Number.isSafeInteger(3); // true
Number.isSafeInteger(1.2); // false
Number.isSafeInteger(9007199254740990); // true
Number.isSafeInteger(9007199254740992); // false

Number.isSafeInteger(Number.MIN_SAFE_INTEGER - 1); // false
Number.isSafeInteger(Number.MIN_SAFE_INTEGER); // true
Number.isSafeInteger(Number.MAX_SAFE_INTEGER); // true
Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1); // false
``````

The implementation of this function is very simple, just compare it with the two boundary values ​​of a safe integer.

``````Number.isSafeInteger = function (n) {
return (
typeof n === "number" &&
Math.round(n) === n &&
Number.MIN_SAFE_INTEGER <= n &&
n <= Number.MAX_SAFE_INTEGER
);
};
``````

When actually using this function, you need to pay attention. Verify that the result of the operation falls within the range of a safe integer. Do not only verify the result of the operation, but also verify each value involved in the operation.

``````Number.isSafeInteger(9007199254740993);
// false
Number.isSafeInteger(990);
// true
Number.isSafeInteger(9007199254740993 - 990);
// true
9007199254740993 - 990;
// return result 9007199254740002
// The correct answer should be 9007199254740003
``````

In the above code, `9007199254740993` is not a safe integer, but `Number.isSafeInteger` will return the result, showing that the calculation result is safe. This is because this number is beyond the accuracy range, and it is stored inside the computer in the form of `9007199254740992`.

``````9007199254740993 === 9007199254740992;
// true
``````

Therefore, if you only verify whether the result of the operation is a safe integer, you may get an incorrect result. The following function can simultaneously verify two operands and the result of the operation.

``````function trusty(left, right, result) {
if (
Number.isSafeInteger(left) &&
Number.isSafeInteger(right) &&
Number.isSafeInteger(result)
) {
return result;
}
throw new RangeError("Operation cannot be trusted!");
}

trusty(9007199254740993, 990, 9007199254740993 - 990);
// RangeError: Operation cannot be trusted!

trusty(1, 2, 3);
// 3
``````

## Math object extension

ES6 adds 17 new math-related methods on the Math object. All these methods are static methods and can only be called on the Math object.

### Math.trunc()

The `Math.trunc` method is used to remove the decimal part of a number and return the integer part.

``````Math.trunc(4.1); // 4
Math.trunc(4.9); // 4
Math.trunc(-4.1); // -4
Math.trunc(-4.9); // -4
Math.trunc(-0.1234); // -0
``````

For non-numerical values, `Math.trunc` internally uses the `Number` method to convert it to a numeric value first.

``````Math.trunc("123.456"); // 123
Math.trunc(true); //1
Math.trunc(false); // 0
Math.trunc(null); // 0
``````

For null values ​​and integer values ​​that cannot be intercepted, `NaN` is returned.

``````Math.trunc(NaN); // NaN
Math.trunc("foo"); // NaN
Math.trunc(); // NaN
Math.trunc(undefined); // NaN
``````

For environments where this method is not deployed, the following code can be used to simulate.

``````Math.trunc =
Math.trunc ||
function (x) {
return x < 0 ? Math.ceil(x) : Math.floor(x);
};
``````

### Math.sign()

The `Math.sign` method is used to determine whether a number is positive, negative, or zero. For non-numeric values, it will first be converted to numeric values.

It will return five values.

-If the parameter is a positive number, return `+1`; -If the parameter is negative, return `-1`; -The parameter is 0, return `0`; -The parameter is -0, return `-0`; -For other values, `NaN` is returned.

``````Math.sign(-5); // -1
Math.sign(5); // +1
Math.sign(0); // +0
Math.sign(-0); // -0
Math.sign(NaN); // NaN
``````

If the parameter is non-numeric, it will be automatically converted to a numeric value. For those values ​​that cannot be converted to numeric values, `NaN` will be returned.

``````Math.sign(""); // 0
Math.sign(true); // +1
Math.sign(false); // 0
Math.sign(null); // 0
Math.sign("9"); // +1
Math.sign("foo"); // NaN
Math.sign(); // NaN
Math.sign(undefined); // NaN
``````

For environments where this method is not deployed, the following code can be used to simulate.

``````Math.sign =
Math.sign ||
function (x) {
x = +x; // convert to a number
if (x === 0 || isNaN(x)) {
return x;
}
return x > 0 ? 1 : -1;
};
``````

### Math.cbrt()

The `Math.cbrt()` method is used to calculate the cube root of a number.

``````Math.cbrt(-1); // -1
Math.cbrt(0); // 0
Math.cbrt(1); // 1
Math.cbrt(2); // 1.2599210498948732
``````

For non-numerical values, the `Math.cbrt()` method internally also uses the `Number()` method to convert it to a number.

``````Math.cbrt("8"); // 2
Math.cbrt("hello"); // NaN
``````

For environments where this method is not deployed, the following code can be used to simulate.

``````Math.cbrt =
Math.cbrt ||
function (x) {
var y = Math.pow(Math.abs(x), 1 / 3);
return x < 0 ? -y : y;
};
``````

### Math.clz32()

The `Math.clz32()` method converts the parameter to the form of a 32-bit unsigned integer, and then returns how many leading zeros are in the 32-bit value.

``````Math.clz32(0); // 32
Math.clz32(1); // 31
Math.clz32(1000); // 22
Math.clz32(0b01000000000000000000000000000000); // 1
Math.clz32(0b00100000000000000000000000000000); // 2
``````

In the above code, the binary form of 0 is all 0s, so there are 32 leading 0s; the binary form of 1 is `0b1`, which only occupies 1 bit, so there are 31 leading 0s in 32 bits; the binary form of 1000 is ` 0b1111101000`, there are 10 bits in total, so there are 22 leading 0s in the 32 bits.

The name of the function `clz32` comes from the abbreviation of "count leading zero bits in 32-bit binary representation of a number".

The left shift operator (`<<`) is directly related to the `Math.clz32` method.

``````Math.clz32(0); // 32
Math.clz32(1); // 31
Math.clz32(1 << 1); // 30
Math.clz32(1 << 2); // 29
Math.clz32(1 << 29); // 2
``````

For decimals, the `Math.clz32` method only considers the integer part.

``````Math.clz32(3.2); // 30
Math.clz32(3.9); // 30
``````

For null values ​​or other types of values, the `Math.clz32` method will first convert them to numeric values, and then calculate them.

``````Math.clz32(); // 32
Math.clz32(NaN); // 32
Math.clz32(Infinity); // 32
Math.clz32(null); // 32
Math.clz32("foo"); // 32
Math.clz32([]); // 32
Math.clz32({}); // 32
Math.clz32(true); // 31
``````

### Math.imul()

The `Math.imul` method returns the result of multiplying two numbers in the form of a 32-bit signed integer, and it returns a 32-bit signed integer.

``````Math.imul(2, 4); // 8
Math.imul(-1, 8); // -8
Math.imul(-2, -2); // 4
``````

If only the last 32 bits are considered, in most cases, the results of `Math.imul(a, b)` and `a * b` are the same, that is, the method is equivalent to the effect of `(a * b)|0` (Partial overflow exceeding 32 bits). The reason why this method needs to be deployed is because JavaScript has a precision limit, and values ​​exceeding 2 to the 53 power cannot be accurately represented. This means that for the multiplication of large numbers, the low-order values ​​are often inaccurate, and the `Math.imul` method can return the correct low-order values.

``````(0x7fffffff * 0x7fffffff) | 0; // 0
``````

The above multiplication formula returns a result of 0. But since the lowest bit of these two binary numbers are both 1, this result is definitely incorrect, because according to binary multiplication, the lowest binary bit of the calculation result should also be 1. This error is because their product exceeds 2 to the 53rd power. JavaScript can't save the extra precision, so the low-order value becomes 0. The `Math.imul` method can return the correct value 1.

``````Math.imul(0x7fffffff, 0x7fffffff); // 1
``````

### Math.fround()

The `Math.fround` method returns a 32-bit single-precision floating-point number form of a number.

For the 32-bit single-precision format, the numerical precision is 24 binary digits (1 hidden bit and 23 significant digits), so for -224 to 224 The integer between (excluding the two endpoints), the returned result is consistent with the parameter itself.

``````Math.fround(0); // 0
Math.fround(1); // 1
Math.fround(2 ** 24 - 1); // 16777215
``````

If the absolute value of the parameter is greater than 224, the returned result will start to lose precision.

``````Math.fround(2 ** 24); // 16777216
Math.fround(2 ** 24 + 1); // 16777216
``````

The main function of the `Math.fround` method is to convert a 64-bit double-precision floating-point number to a 32-bit single-precision floating-point number. If the precision of the decimal exceeds 24 binary digits, the return value will be different from the original value, otherwise the return value will not change (that is, the same as the 64-bit double precision value).

``````// Effective accuracy is not lost
Math.fround(1.125); // 1.125
Math.fround(7.25); // 7.25

// Lost precision
Math.fround(0.3); // 0.30000001192092896
Math.fround(0.7); // 0.699999988079071
Math.fround(1.0000000123); // 1
``````

For `NaN` and `Infinity`, this method returns the original value. For other types of non-numeric values, the `Math.fround` method will first convert them to numeric values, and then return single-precision floating-point numbers.

``````Math.fround(NaN); // NaN
Math.fround(Infinity); // Infinity

Math.fround("5"); // 5
Math.fround(true); // 1
Math.fround(null); // 0
Math.fround([]); // 0
Math.fround({}); // NaN
``````

For environments where this method is not deployed, the following code can be used to simulate.

``````Math.fround =
Math.fround ||
function (x) {
return new Float32Array([x])[0];
};
``````

### Math.hypot()

The `Math.hypot` method returns the square root of the sum of squares of all parameters.

``````Math.hypot(3, 4); // 5
Math.hypot(3, 4, 5); // 7.0710678118654755
Math.hypot(); // 0
Math.hypot(NaN); // NaN
Math.hypot(3, 4, "foo"); // NaN
Math.hypot(3, 4, "5"); // 7.0710678118654755
Math.hypot(-3); // 3
``````

In the above code, the square of 3 plus the square of 4 is equal to the square of 5.

If the parameter is not a numeric value, the `Math.hypot` method will convert it to a numeric value. As long as there is a parameter that cannot be converted to a value, NaN will be returned.

### Logarithmic method

ES6 adds 4 logarithmic correlation methods.

(1) Math.expm1()

`Math.expm1(x)` returns ex-1, which is `Math.exp(x)-1`.

``````Math.expm1(-1); // -0.6321205588285577
Math.expm1(0); // 0
Math.expm1(1); // 1.718281828459045
``````

For environments where this method is not deployed, the following code can be used to simulate.

``````Math.expm1 =
Math.expm1 ||
function (x) {
return Math.exp(x) - 1;
};
``````

(2)Math.log1p()

The `Math.log1p(x)` method returns the natural logarithm of `1 + x`, which is `Math.log(1 + x)`. If `x` is less than -1, return `NaN`.

``````Math.log1p(1); // 0.6931471805599453
Math.log1p(0); // 0
Math.log1p(-1); // -Infinity
Math.log1p(-2); // NaN
``````

For environments where this method is not deployed, the following code can be used to simulate.

``````Math.log1p =
Math.log1p ||
function (x) {
return Math.log(1 + x);
};
``````

(3)Math.log10()

`Math.log10(x)` returns the base 10 logarithm of `x`. If `x` is less than 0, NaN is returned.

``````Math.log10(2); // 0.3010299956639812
Math.log10(1); // 0
Math.log10(0); // -Infinity
Math.log10(-2); // NaN
Math.log10(100000); // 5
``````

For environments where this method is not deployed, the following code can be used to simulate.

``````Math.log10 =
Math.log10 ||
function (x) {
return Math.log(x) / Math.LN10;
};
``````

(4)Math.log2()

`Math.log2(x)` returns the base 2 logarithm of `x`. If `x` is less than 0, NaN is returned.

``````Math.log2(3); // 1.584962500721156
Math.log2(2); // 1
Math.log2(1); // 0
Math.log2(0); // -Infinity
Math.log2(-2); // NaN
Math.log2(1024); // 10
Math.log2(1 << 29); // 29
``````

For environments where this method is not deployed, the following code can be used to simulate.

``````Math.log2 =
Math.log2 ||
function (x) {
return Math.log(x) / Math.LN2;
};
``````

### Hyperbolic function method

ES6 added 6 hyperbolic function methods.

-`Math.sinh(x)` returns the hyperbolic sine of `x` -`Math.cosh(x)` returns the hyperbolic cosine of `x` -`Math.tanh(x)` returns the hyperbolic tangent of `x` -`Math.asinh(x)` returns the inverse hyperbolic sine of `x` -`Math.acosh(x)` returns the inverse hyperbolic cosine of `x` -`Math.atanh(x)` returns the inverse hyperbolic tangent of `x`

## Exponential operator

ES2016 added a new exponent operator (`**`).

``````2 ** 2; // 4
2 ** 3; // 8
``````

A feature of this operator is right associativity, rather than the common left associativity. When multiple exponent operators are used together, the calculation starts from the rightmost.

``````// equivalent to 2 ** (3 ** 2)
2 ** (3 ** 2);
// 512
``````

In the above code, the second exponential operator is calculated first, not the first.

The exponent operator can be combined with the equal sign to form a new assignment operator (`**=`).

``````let a = 1.5;
a **= 2;
// equivalent to a = a * a;

let b = 4;
b **= 3;
// equivalent to b = b * b * b;
``````

## BigInt data type

### Introduction

All numbers in JavaScript are saved as 64-bit floating point numbers, which brings two major limitations to the representation of values. One is that the precision of a value can only reach 53 binary digits (equivalent to 16 decimal digits). Integers larger than this range cannot be accurately represented by JavaScript, which makes JavaScript unsuitable for accurate scientific and financial calculations. The second is a value greater than or equal to 2 to the power of 1024, which JavaScript cannot represent and will return `Infinity`.

``````// The value exceeds 53 binary digits, and the precision cannot be maintained
Math.pow(2, 53) === Math.pow(2, 53) + 1; // true

// A value exceeding 2 to the power of 1024, cannot be represented
Math.pow(2, 1024); // Infinity
``````

ES2020 introduced a new data type BigInt (big integer) to solve this problem, which is the eighth data type of ECMAScript. BigInt is only used to represent integers, there is no limit on the number of digits, and integers of any number of digits can be accurately represented.

``````const a = 2172141653n;
const b = 15346349309n;

// BigInt can maintain accuracy
a * b; // 33334444555566667777n

// Ordinary integers cannot maintain precision
Number(a) * Number(b); // 33334444555566670000
``````

In order to distinguish from the Number type, the data of the BigInt type must be suffixed with `n`.

``````1234; // ordinary integer
1234n; // BigInt

// Operation of BigInt
1n + 2n; // 3n
``````

BigInt can also be expressed in various bases, all with the suffix `n`.

``````0b1101n; // Binary
0o777n; // octal
``````

BigInt and ordinary integer are two kinds of values, and they are not equal.

``````42n === 42; // false
``````

The `typeof` operator returns `bigint` for data of type BigInt.

``````typeof 123n; //'bigint'
``````

BigInt can use negative sign (`-`), but cannot use positive sign (`+`) because it will conflict with asm.js.

``````-42n + // correct
42n; // report an error
``````

JavaScript could not calculate the factorial of 70 (that is, `70!`) because it exceeded the precision that can be expressed.

``````let p = 1;
for (let i = 1; i <= 70; i++) {
p *= i;
}
console.log(p); // 1.197857166996989e+100
``````

Now that large integers are supported, it's fine. Run the following code in the browser's developer tool, and it will be OK.

``````let p = 1n;
for (let i = 1n; i <= 70n; i++) {
p *= i;
}
console.log(p); // 11978571...00000000n
``````

### BigInt Object

JavaScript natively provides the `BigInt` object, which can be used as a constructor to generate BigInt type values. The conversion rules are basically the same as `Number()`, and other types of values ​​are converted to BigInt.

``````BigInt(123); // 123n
BigInt("123"); // 123n
BigInt(false); // 0n
BigInt(true); // 1n
``````

The `BigInt()` constructor must have parameters, and the parameters must be converted to values ​​normally. The following usages will report errors.

``````new BigInt(); // TypeError
BigInt(undefined); //TypeError
BigInt(null); // TypeError
BigInt("123n"); // SyntaxError
BigInt("abc"); // SyntaxError
``````

In the above code, it is especially worth noting that the string `123n` cannot be parsed into Number type, so an error will be reported.

If the parameter is a decimal, an error will be reported.

``````BigInt(1.5); // RangeError
BigInt("1.5"); // SyntaxError
``````

The BigInt object inherits two instance methods of the Object object.

-`BigInt.prototype.toString()` -`BigInt.prototype.valueOf()`

It also inherits an instance method of the Number object.

-`BigInt.prototype.toLocaleString()`

In addition, three static methods are provided.

-`BigInt.asUintN(width, BigInt)`: The given BigInt is converted to the corresponding value between 0 and 2width-1. -`BigInt.asIntN(width, BigInt)`: The given BigInt is converted to the corresponding value from -2width-1 to 2width-1-1. -`BigInt.parseInt(string[, radix])`: Approximately `Number.parseInt()`, which converts a string into a BigInt in the specified base.

``````const max = 2n ** (64n - 1n) - 1n;

BigInt.asIntN(64, max);
// 9223372036854775807n
BigInt.asIntN(64, max + 1n);
// -9223372036854775808n
BigInt.asUintN(64, max + 1n);
// 9223372036854775808n
``````

In the above code, `max` is the maximum value that a 64-bit signed BigInt can represent. If you add `1n` to this value, `BigInt.asIntN()` will return a negative value, because the new bit will be interpreted as a sign bit. The `BigInt.asUintN()` method can return the result correctly because there is no sign bit.

If the number of digits specified by `BigInt.asIntN()` and `BigInt.asUintN()` is less than the number of digits, then the head bit will be discarded.

``````const max = 2n ** (64n - 1n) - 1n;

BigInt.asIntN(32, max); // -1n
BigInt.asUintN(32, max); // 4294967295n
``````

In the above code, `max` is a 64-bit BigInt. If it is converted to 32 bits, the previous 32 bits will be discarded.

The following is an example of `BigInt.parseInt()`.

``````// Comparison of Number.parseInt() and BigInt.parseInt()
Number.parseInt("9007199254740993", 10);
// 9007199254740992
BigInt.parseInt("9007199254740993", 10);
// 9007199254740993n
``````

In the above code, because the effective number exceeds the maximum limit, the result returned by the `Number.parseInt` method is inaccurate, and the `BigInt.parseInt` method correctly returns the corresponding BigInt.

For binary arrays, BigInt adds two new types `BigUint64Array` and `BigInt64Array`, both of which return 64-bit BigInt. The instance methods `DataView.prototype.getBigInt64()` and `DataView.prototype.getBigUint64()` of the `DataView` object also return BigInt.

### Conversion rules

You can use the three methods `Boolean()`, `Number()` and `String()` to convert BigInt to Boolean, numeric and string types.

``````Boolean(0n); // false
Boolean(1n); // true
Number(1n); // 1
String(1n); // "1"
``````

In the above code, pay attention to the last example, the suffix `n` will disappear when converted to a string.

In addition, the negation operator (`!`) can also convert BigInt to a Boolean value.

``````!0n; // true
!1n; // false
``````

### computation

In terms of mathematical operations, the four binary operators `+`, `-`, `*`, and `**` of the BigInt type have the same behavior as the Number type. The division operation `/` will round off the decimal part and return an integer.

``````9n / 5n;
// 1n
``````

Almost all numerical operators can be used in BigInt, but there are two exceptions.

-Unsigned right shift operator `>>>` -Unary positive operator `+`

The above two operators will report errors when used in BigInt. The former is because the `>>>` operator is unsigned, but BigInt is always signed, which makes the operation meaningless and is completely equivalent to the right shift operator `>>`. The latter is because the unary operator `+` always returns the Number type in asm.js. In order not to damage asm.js, it is stipulated that `+1n` will report an error.

BigInt cannot be mixed with ordinary values.

``````1n + 1.3; // error
``````

The above code reports an error because whether it returns BigInt or Number, it will cause the loss of precision information. For example, if the expression `(2n**53n + 1n) + 0.5` returns the BigInt type, the fractional part of `0.5` will be lost; if it returns the Number type, the effective precision can only maintain 53 digits, resulting in a decrease in precision.

For the same reason, if the parameter of a standard library function is expected to be of type Number, but the result is a BigInt, an error will be reported.

``````// wrong way
Math.sqrt(4n); // error

// correct writing
Math.sqrt(Number(4n)); // 2
``````

In the above code, the parameter of `Math.sqrt` is expected to be of Number type. If it is BigInt, an error will be reported. You must first use the `Number` method to transfer the type before calculation.

In asm.js, `|0` following a value will return a 32-bit integer. According to the rule that the operation cannot be mixed with the Number type, BigInt will report an error if it is operated with `|0`.

``````1n | 0; // error
``````

### Other operations

The Boolean value corresponding to BigInt is consistent with the Number type, that is, `0n` will be converted to `false`, and other values ​​will be converted to `true`.

``````if (0n) {
console.log("if");
} else {
console.log("else");
}
// else
``````

In the above code, `0n` corresponds to `false`, so it will enter the `else` clause.

Comparison operators (such as `>`) and equality operators (`==`) allow BigInt to be mixed with other types of values, because they do not lose precision.

``````0n < 1; // true
0n < true; // true
0n == 0; // true
0n == false; // true
0n === 0; // false
``````

When BigInt is mixed with a string, it will be converted to a string first, and then the operation will be performed.

``````"" + 123n; // "123"
``````