Я ищу способ выполнить побитовое И для 64-битного целого числа в JavaScript.
JavaScript преобразует все свои значения типа double в 32-разрядные целые числа со знаком для выполнения побитовых операций (подробности здесь).
Я ищу способ выполнить побитовое И для 64-битного целого числа в JavaScript.
JavaScript преобразует все свои значения типа double в 32-разрядные целые числа со знаком для выполнения побитовых операций (подробности здесь).
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-битных числа, то применить побитовое И так же просто, как применить 2 побитовых И к младшему и старшему 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
Вот код для чисел 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;
}
&
в выражениях для h
и l
.
- person malthe; 04.12.2018
Теперь это можно сделать с помощью нового встроенного числового типа BigInt. В настоящее время BigInt (июль 2019 г.) доступен только в определенных браузерах, подробности см. По следующей ссылке:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt
Я протестировал побитовые операции с использованием BigInts в Chrome 67 и могу подтвердить, что они работают должным образом с 64-битными значениями.
Javascript не поддерживает 64-битные целые числа из коробки. Вот что я в итоге сделал:
Long
.Long
из младшего и старшего битаПримечание: для работы приведенного ниже примера кода необходимо загрузить long.js.
// Handy to output leading zeros to make it easier to compare the bits when outputting to the console
function zeroPad(num, places){
var zero = places - num.length + 1;
return Array(+(zero > 0 && zero)).join('0') + num;
}
// 2^3 = 8
var val1 = Long.fromString('8', 10);
var val1High = val1.getHighBitsUnsigned();
var val1Low = val1.getLowBitsUnsigned();
// 2^61 = 2305843009213693960
var val2 = Long.fromString('2305843009213693960', 10);
var val2High = val2.getHighBitsUnsigned();
var val2Low = val2.getLowBitsUnsigned();
console.log('2^3 & (2^3 + 2^63)')
console.log(zeroPad(val1.toString(2), 64));
console.log(zeroPad(val2.toString(2), 64));
var bitwiseAndResult = Long.fromBits(val1Low & val2Low, val1High & val2High, true);
console.log(bitwiseAndResult);
console.log(zeroPad(bitwiseAndResult.toString(2), 64));
console.log('Correlation betwen val1 and val2 ?');
console.log(bitwiseAndResult > 0);
Вывод в консоль:
2^3
0000000000000000000000000000000000000000000000000000000000001000
2^3 + 2^63
0010000000000000000000000000000000000000000000000000000000001000
2 ^ 3 и (2 ^ 3 + 2 ^ 63)
0000000000000000000000000000000000000000000000000000000000001000
Корреляция между val1 и val2?
правда
В библиотеке Closure есть goog.math.Long
с поразрядным add()
методом. .