29 lines
2 KiB
Markdown
29 lines
2 KiB
Markdown
Всё дело в том, что побитовые операции преобразуют число в 32-битное целое.
|
||
|
||
Обычно число в JavaScript имеет 64-битный формат с плавающей точкой. При этом часть битов (`52`) отведены под цифры, часть (`11`) отведены под хранение номера позиции, на которой стоит десятичная точка, и один бит -- знак числа.
|
||
|
||
Это означает, что максимальное целое число, которое можно хранить, занимает `52` бита.
|
||
|
||
Число `12345678912345` в двоичном виде: `10110011101001110011110011100101101101011001` (44 цифры).
|
||
|
||
Побитовый оператор `^` преобразует его в 32-битное путём отбрасывания десятичной точки и "лишних" старших цифр. При этом, так как число большое и старшие биты здесь ненулевые, то, естественно, оно изменится.
|
||
|
||
Вот ещё пример:
|
||
|
||
```js
|
||
//+ run
|
||
// в двоичном виде 1000000000000000000000000000000 (31 цифры)
|
||
alert( Math.pow(2, 30) ); // 1073741824
|
||
alert( Math.pow(2, 30) ^ 0 ); // 1073741824, всё ок, длины хватает
|
||
|
||
// в двоичном виде 100000000000000000000000000000000 (33 цифры)
|
||
alert( Math.pow(2, 32) ); // 4294967296
|
||
alert( Math.pow(2, 32) ^ 0 ); // 0, отброшены старшие цифры, остались нули
|
||
|
||
// пограничный случай
|
||
// в двоичном виде 10000000000000000000000000000000 (32 цифры)
|
||
alert( Math.pow(2, 31) ); // 2147483648
|
||
alert( Math.pow(2, 31) ^ 0 ); // -2147483648, ничего не отброшено,
|
||
// но первый бит 1 теперь стоит в начале числа и является знаковым
|
||
```
|
||
|