bigint
This commit is contained in:
parent
438e66d952
commit
a70c4306d7
4 changed files with 168 additions and 45 deletions
|
@ -42,7 +42,7 @@ Only comments may appear above `"use strict"`.
|
|||
```warn header="There's no way to cancel `use strict`"
|
||||
There is no directive like `"no use strict"` that reverts the engine to old behavior.
|
||||
|
||||
Once we enter strict mode, there's no return.
|
||||
Once we enter strict mode, there's no going back.
|
||||
```
|
||||
|
||||
## Browser console
|
||||
|
|
|
@ -12,7 +12,7 @@ Programming languages that allow such things are called "dynamically typed", mea
|
|||
|
||||
There are eight basic data types in JavaScript. Here, we'll cover them in general and in the next chapters we'll talk about each of them in detail.
|
||||
|
||||
## A number
|
||||
## Number
|
||||
|
||||
```js
|
||||
let n = 123;
|
||||
|
@ -62,14 +62,33 @@ Special numeric values formally belong to the "number" type. Of course they are
|
|||
|
||||
We'll see more about working with numbers in the chapter <info:number>.
|
||||
|
||||
## A string
|
||||
## BigInt
|
||||
|
||||
In JavaScript, the "number" type cannot represent integer values larger than <code>2<sup>53</sup></code> (or less than <code>-2<sup>53</sup></code> for negatives), that's a technical limitation caused by their internal representation. That's about 16 decimal digits, so for most purposes the limitation isn't a problem, but sometimes we need really big numbers, e.g. for cryptography or microsecond-precision timestamps.
|
||||
|
||||
`BigInt` type was recently added to the language to represent integers of arbitrary length.
|
||||
|
||||
A `BigInt` is created by appending `n` to the end of an integer literal:
|
||||
|
||||
```js
|
||||
// the "n" at the end means it's a BigInt
|
||||
const bigInt = 1234567890123456789012345678901234567890n;
|
||||
```
|
||||
|
||||
As `BigInt` numbers are rarely needed, we devoted them a separate chapter <info:bigint>.
|
||||
|
||||
```smart header="Compatability issues"
|
||||
Right now `BigInt` is supported in Firefox and Chrome, but not in Safari/IE/Edge.
|
||||
```
|
||||
|
||||
## String
|
||||
|
||||
A string in JavaScript must be surrounded by quotes.
|
||||
|
||||
```js
|
||||
let str = "Hello";
|
||||
let str2 = 'Single quotes are ok too';
|
||||
let phrase = `can embed ${str}`;
|
||||
let phrase = `can embed another ${str}`;
|
||||
```
|
||||
|
||||
In JavaScript, there are 3 types of quotes.
|
||||
|
@ -78,7 +97,7 @@ In JavaScript, there are 3 types of quotes.
|
|||
2. Single quotes: `'Hello'`.
|
||||
3. Backticks: <code>`Hello`</code>.
|
||||
|
||||
Double and single quotes are "simple" quotes. There's no difference between them in JavaScript.
|
||||
Double and single quotes are "simple" quotes. There's practically no difference between them in JavaScript.
|
||||
|
||||
Backticks are "extended functionality" quotes. They allow us to embed variables and expressions into a string by wrapping them in `${…}`, for example:
|
||||
|
||||
|
@ -102,12 +121,12 @@ alert( "the result is ${1 + 2}" ); // the result is ${1 + 2} (double quotes do n
|
|||
We'll cover strings more thoroughly in the chapter <info:string>.
|
||||
|
||||
```smart header="There is no *character* type."
|
||||
In some languages, there is a special "character" type for a single character. For example, in the C language and in Java it is `char`.
|
||||
In some languages, there is a special "character" type for a single character. For example, in the C language and in Java it is called "char".
|
||||
|
||||
In JavaScript, there is no such type. There's only one type: `string`. A string may consist of only one character or many of them.
|
||||
```
|
||||
|
||||
## A boolean (logical type)
|
||||
## Boolean (logical type)
|
||||
|
||||
The boolean type has only two values: `true` and `false`.
|
||||
|
||||
|
@ -180,31 +199,6 @@ All other types are called "primitive" because their values can contain only a s
|
|||
|
||||
The `symbol` type is used to create unique identifiers for objects. We mention it here for completeness, but we'll study it after objects.
|
||||
|
||||
## BigInt
|
||||
|
||||
In JavaScript, the Number type cannot represent integer values larger than 2<sup>53</sup>-1. This limitation has forced many of us to use inefficient workarounds. BigInt is a new data type intended to fix just that. A BigInt is created by appending n to the end of an integer literal — 10n — or by calling the function BigInt().
|
||||
|
||||
```js run
|
||||
const theBiggestInt = 9007199254740991n;
|
||||
|
||||
const huge = BigInt(9007199254740991);
|
||||
|
||||
alert(typeof biggestInt); // shows "bigint"
|
||||
|
||||
alert(typeof huge); // shows "bigint"
|
||||
```
|
||||
Bigint can mostly be used like number but there are some key differences
|
||||
- Most math operatioons work on it normally
|
||||
- It cannot be mixed and match with number while apllying binary operations it has to be coerced into each other but be careful it can lead to some precision losses
|
||||
- The / operator also works as expected with whole numbers. However, since these are BigInts and not BigDecimals, this operation will round towards 0, which is to say, it will not return any fractional digits.
|
||||
|
||||
To know more in detail about the java script newest addition in prmitive types please visit [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) docs for it
|
||||
|
||||
|
||||
```smart header="Compatability issues"
|
||||
Right now it only compatible with firefox and chrome but is not supported in Safari.
|
||||
```
|
||||
|
||||
## The typeof operator [#type-typeof]
|
||||
|
||||
The `typeof` operator returns the type of the argument. It's useful when we want to process values of different types differently or just want to do a quick check.
|
||||
|
@ -223,6 +217,8 @@ typeof undefined // "undefined"
|
|||
|
||||
typeof 0 // "number"
|
||||
|
||||
typeof 10n // "bigint"
|
||||
|
||||
typeof true // "boolean"
|
||||
|
||||
typeof "foo" // "string"
|
||||
|
@ -248,19 +244,18 @@ The last three lines may need additional explanation:
|
|||
2. The result of `typeof null` is `"object"`. That's wrong. It is an officially recognized error in `typeof`, kept for compatibility. Of course, `null` is not an object. It is a special value with a separate type of its own. So, again, this is an error in the language.
|
||||
3. The result of `typeof alert` is `"function"`, because `alert` is a function. We'll study functions in the next chapters where we'll also see that there's no special "function" type in JavaScript. Functions belong to the object type. But `typeof` treats them differently, returning `"function"`. That's not quite correct, but very convenient in practice.
|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
There are 8 basic data types in JavaScript.
|
||||
|
||||
- `number` for numbers of any kind: integer or floating-point.
|
||||
- `number` for numbers of any kind: integer or floating-point, integers are limited by ±2<sup>53</sup>.
|
||||
- `bigint` is for integer numbers of arbitrary length.
|
||||
- `string` for strings. A string may have one or more characters, there's no separate single-character type.
|
||||
- `boolean` for `true`/`false`.
|
||||
- `null` for unknown values -- a standalone type that has a single value `null`.
|
||||
- `undefined` for unassigned values -- a standalone type that has a single value `undefined`.
|
||||
- `object` for more complex data structures.
|
||||
- `symbol` for unique identifiers.
|
||||
- `bigint` is for displaying numbers greater than 2<sup>53</sup>-1
|
||||
|
||||
The `typeof` operator allows us to see which type is stored in a variable.
|
||||
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
# Numbers
|
||||
|
||||
All numbers in JavaScript are stored in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754-2008_revision), also known as "double precision floating point numbers".
|
||||
In modern JavaScript, there are two types of numbers:
|
||||
|
||||
Let's expand upon what we currently know about them.
|
||||
1. Regular numbers in JavaScript are stored in 64-bit format [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754-2008_revision), also known as "double precision floating point numbers". These are numbers that we're using most of the time, and we'll talk about them in this chapter.
|
||||
|
||||
2. BigInt numbers, to represent integers of arbitrary length. They are sometimes needed, because a regular number can't exceed <code>2<sup>53</sup></code> or be less than <code>-2<sup>53</sup></code>. As bigints are used in few special areas, we devote them a special chapter <info:bigint>.
|
||||
|
||||
So here we'll talk about regular numbers. Let's expand our knowledge of them.
|
||||
|
||||
## More ways to write a number
|
||||
|
||||
|
@ -29,14 +33,13 @@ In other words, `"e"` multiplies the number by `1` with the given zeroes count.
|
|||
1.23e6 = 1.23 * 1000000
|
||||
```
|
||||
|
||||
|
||||
Now let's write something very small. Say, 1 microsecond (one millionth of a second):
|
||||
|
||||
```js
|
||||
let ms = 0.000001;
|
||||
```
|
||||
|
||||
Just like before, using `"e"` can help. If we'd like to avoid writing the zeroes explicitly, we could say:
|
||||
Just like before, using `"e"` can help. If we'd like to avoid writing the zeroes explicitly, we could say the same as:
|
||||
|
||||
```js
|
||||
let ms = 1e-6; // six zeroes to the left from 1
|
||||
|
@ -271,13 +274,11 @@ JavaScript doesn't trigger an error in such events. It does its best to fit the
|
|||
```smart header="Two zeroes"
|
||||
Another funny consequence of the internal representation of numbers is the existence of two zeroes: `0` and `-0`.
|
||||
|
||||
That's because a sign is represented by a single bit, so every number can be positive or negative, including a zero.
|
||||
That's because a sign is represented by a single bit, so it can be set or not set for any number including a zero.
|
||||
|
||||
In most cases the distinction is unnoticeable, because operators are suited to treat them as the same.
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Tests: isFinite and isNaN
|
||||
|
||||
Remember these two special numeric values?
|
||||
|
@ -409,10 +410,10 @@ There are more functions and constants in `Math` object, including trigonometry,
|
|||
|
||||
## Summary
|
||||
|
||||
To write big numbers:
|
||||
To write numbers with many zeroes:
|
||||
|
||||
- Append `"e"` with the zeroes count to the number. Like: `123e6` is `123` with 6 zeroes.
|
||||
- A negative number after `"e"` causes the number to be divided by 1 with given zeroes. That's for one-millionth or such.
|
||||
- Append `"e"` with the zeroes count to the number. Like: `123e6` is the same as `123` with 6 zeroes `123000000`.
|
||||
- A negative number after `"e"` causes the number to be divided by 1 with given zeroes. E.g. `123e-6` means `0.000123` (`123` millionth).
|
||||
|
||||
For different numeral systems:
|
||||
|
||||
|
|
127
1-js/99-js-misc/05-bigint/article.md
Normal file
127
1-js/99-js-misc/05-bigint/article.md
Normal file
|
@ -0,0 +1,127 @@
|
|||
# BigInt
|
||||
|
||||
[recent caniuse="bigint"]
|
||||
|
||||
`BigInt` is a special numeric type that provides support for integers of arbitrary length.
|
||||
|
||||
A bigint is created by appending `n` to the end of an integer literal or by calling the function `BigInt` that creates bigints from strings, numbers etc.
|
||||
|
||||
```js
|
||||
const bigint = 1234567890123456789012345678901234567890n;
|
||||
|
||||
const sameBigint = BigInt("1234567890123456789012345678901234567890");
|
||||
|
||||
const bigintFromNumber = BigInt(10); // same as 10n
|
||||
```
|
||||
|
||||
## Math operators
|
||||
|
||||
`BigInt` can mostly be used like a regular number, for example:
|
||||
|
||||
```js run
|
||||
alert(1n + 2n); // 3
|
||||
|
||||
alert(5n / 2n); // 2
|
||||
```
|
||||
|
||||
Please note: the division `5/2` returns the result rounded towards zero, without the decimal part. All operations on bigints return bigints.
|
||||
|
||||
We can't mix bigints and regular numbers:
|
||||
|
||||
```js run
|
||||
alert(1n + 2); // Error: Cannot mix BigInt and other types
|
||||
```
|
||||
|
||||
We should explicitly convert them if needed: using either `BigInt()` or `Number()`, like this:
|
||||
|
||||
```js run
|
||||
let bigint = 1n;
|
||||
let number = 2;
|
||||
|
||||
// number to bigint
|
||||
alert(bigint + BigInt(number)); // 3
|
||||
|
||||
// bigint to number
|
||||
alert(Number(bigint) + number); // 3
|
||||
```
|
||||
|
||||
The conversion of bigint to number is always silent, but if the bigint is too huge and won't fit the number type, then extra bits will be cut off, causing a precision loss.
|
||||
|
||||
````smart header="The unary plus is not supported on bigints"
|
||||
The unary plus operator `+value` is a well-known way to convert a `value` to number.
|
||||
|
||||
On bigints it's not supported, to avoid confusion:
|
||||
```js run
|
||||
let bigint = 1n;
|
||||
|
||||
alert( +bigint ); // error
|
||||
```
|
||||
````
|
||||
|
||||
## Comparisons
|
||||
|
||||
Comparisons, such as `<`, `>` work with bigints and numbers just fine:
|
||||
|
||||
```js run
|
||||
alert( 2n > 1n ); // true
|
||||
|
||||
alert( 2n > 1 ); // true
|
||||
```
|
||||
|
||||
As numbers and bigints belong to different types, they can be equal `==`, but not strictly equal `===`:
|
||||
|
||||
```js run
|
||||
alert( 1 == 1n ); // true
|
||||
|
||||
alert( 1 === 1n ); // false
|
||||
```
|
||||
|
||||
## Boolean operations
|
||||
|
||||
When inside `if` or other boolean operations, bigints behave like numbers.
|
||||
|
||||
For instance, in `if`, bigint `0n` is falsy, other values are truthy:
|
||||
|
||||
```js run
|
||||
if (0n) {
|
||||
// never executes
|
||||
}
|
||||
```
|
||||
|
||||
Boolean operators, such as `||`, `&&` and others also work with bigints similar to numbers:
|
||||
|
||||
```js run
|
||||
alert( 1n || 2 ); // 1
|
||||
|
||||
alert( 0n || 2 ); // 2
|
||||
```
|
||||
|
||||
## Polyfills
|
||||
|
||||
Polyfilling bigints is tricky. The reason is that many JavaScript operators, such as `+`, `-` and so on behave differently with bigints compared to regular numbers.
|
||||
|
||||
For example, division of bigints always returns an integer.
|
||||
|
||||
To emulate such behavior, a polyfill would need to replace all such operators with its functions. But doing so is cumbersome and would cost a lot of performance.
|
||||
|
||||
So, there's no well-known good polyfill.
|
||||
|
||||
Although, the other way around is proposed by the developers of [https://github.com/GoogleChromeLabs/jsbi](JSBI) library.
|
||||
|
||||
They suggest to use JSBI library calls instead of native bigints:
|
||||
|
||||
| Operation | native `BigInt` | JSBI |
|
||||
|-----------|-----------------|------|
|
||||
| Creation from Number | `a = BigInt(789)` | `a = JSBI.BigInt(789)` |
|
||||
| Addition | `c = a + b` | `c = JSBI.add(a, b)` |
|
||||
| Subtraction | `c = a - b` | `c = JSBI.subtract(a, b)` |
|
||||
| ... | ... | ... |
|
||||
|
||||
...And then use the polyfill (Babel plugin) to convert JSBI calls to native bigints for those browsers that support them.
|
||||
|
||||
In other words, this approach suggests that we write code in JSBI instead of native bigints. But JSBI works with numbers as with bigints internally, closely following the specification, so the code will be "bigint-ready".
|
||||
|
||||
## References
|
||||
|
||||
- [MDN docs on BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
|
||||
- [Specification](https://tc39.es/ecma262/#sec-bigint-objects).
|
Loading…
Add table
Add a link
Reference in a new issue