Я ищу способ выполнения побитового И 64-разрядного целого числа в JavaScript.

JavaScript преобразует все свои двойные значения в 32-разрядные целые числа со знаком для выполнения побитовых операций (Подробности здесь).

36
Toby Hede 6 Июн 2010 в 09:28

4 ответа

Лучший ответ

Javascript представляет все числа в виде 64-битных двойной точности IEEE 754 с плавающей запятой (см. спецификацию ECMAscript, раздел 8.5. ) Все натуральные числа до 2 ^ 53 могут быть точно закодированы. Большие целые числа обрезают свои младшие значащие биты. Это оставляет вопрос о том, как вы можете даже представить 64-битное целое число в Javascript - тип данных с собственным числом явно не может точно представлять 64-битное целое число.

Следующее иллюстрирует это. Хотя javascript выглядит способным анализировать шестнадцатеричные числа, представляющие 64-битные числа, базовое числовое представление не содержит 64 бит. Попробуйте следующее в вашем браузере:

<html>
  <head>
    <script language="javascript">
      function showPrecisionLimits() {
        document.getElementById("r50").innerHTML = 0x0004000000000001 - 0x0004000000000000;
        document.getElementById("r51").innerHTML = 0x0008000000000001 - 0x0008000000000000;
        document.getElementById("r52").innerHTML = 0x0010000000000001 - 0x0010000000000000;
        document.getElementById("r53").innerHTML = 0x0020000000000001 - 0x0020000000000000;
        document.getElementById("r54").innerHTML = 0x0040000000000001 - 0x0040000000000000;
      }
    </script>
  </head>
  <body onload="showPrecisionLimits()">
    <p>(2^50+1) - (2^50) = <span id="r50"></span></p>
    <p>(2^51+1) - (2^51) = <span id="r51"></span></p>
    <p>(2^52+1) - (2^52) = <span id="r52"></span></p>
    <p>(2^53+1) - (2^53) = <span id="r53"></span></p>
    <p>(2^54+1) - (2^54) = <span id="r54"></span></p>
  </body>
</html>

В Firefox, Chrome и IE я получаю следующее. Если числа были сохранены в их полной 64-битной славе, результат должен был быть 1 для всех вычитаний. Вместо этого вы можете видеть, как теряется разница между 2 ^ 53 + 1 и 2 ^ 53.

(2^50+1) - (2^50) = 1
(2^51+1) - (2^51) = 1
(2^52+1) - (2^52) = 1
(2^53+1) - (2^53) = 0
(2^54+1) - (2^54) = 0

Так что ты можешь сделать?

Если вы решите представить 64-разрядное целое число в виде двух 32-разрядных чисел, тогда применение побитового И так же просто, как применение двух побитовых И, к старшему и старшему 32-битным «словам».

Например:

var a = [ 0x0000ffff, 0xffff0000 ];
var b = [ 0x00ffff00, 0x00ffff00 ];
var c = [ a[0] & b[0], a[1] & b[1] ];

document.body.innerHTML = c[0].toString(16) + ":" + c[1].toString(16);

Получает вас:

ff00:ff0000
33
Michael Gaskill 19 Май 2016 в 03:10

Теперь это можно сделать с помощью нового встроенного числового типа BigInt. В настоящее время BigInt (июль 2019 года) доступен только в определенных браузерах, подробности см. По следующей ссылке:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

Я протестировал побитовые операции с использованием BigInts в Chrome 67 и могу подтвердить, что они работают должным образом с 64-битными значениями.

3
Gav G 5 Июл 2019 в 23:09

Библиотека Closure имеет goog.math.Long с побитовый add() метод.

4
Jesse 13 Июн 2018 в 06:38

Вот код для чисел AND int64, вы можете заменить AND другой побитовой операцией

function and(v1, v2) {
    var hi = 0x80000000;
    var low = 0x7fffffff;
    var hi1 = ~~(v1 / hi);
    var hi2 = ~~(v2 / hi);
    var low1 = v1 & low;
    var low2 = v2 & low;
    var h = hi1 & hi2;
    var l = low1 & low2;
    return h*hi + l;
}
10
Andrey 28 Апр 2017 в 11:39