Беззнаковое целое в Javascript
Я работаю над страницей, обрабатывающей информацию о IP-адресе, но она задыхается от того, что целые числа подписаны. Я использую побитовые операторы, чтобы ускорить его, но 64-й бит (подписанный/неподписанный флаг) испортил его.
Есть ли способ заставить число быть неподписанным в Javascript? Кажется, что он работает нормально, пока подсеть больше 30 или меньше 2.
Попробуйте следующее:
<html>
<body>
<script type='text/javascript'>
document.write( (1 << 30) +"<br/>");
document.write( (1 << 31) +"<br/>");
document.write( (1 << 32) +"<br/>");
</script>
</body>
</html>
Результат:
1073741824 -2147483648 1
Ответы
Ответ 1
document.write( (1 << 31) +"<br/>");
Оператор <<
определяется как работающий с подписанными 32-битными целыми числами (преобразованный из собственного хранилища чисел с плавающей точкой с двойной точностью). Поэтому 1<<31
должно приводить к отрицательному числу.
Единственный оператор JavaScript, который работает с 32-разрядными целыми числами без знака, равен >>>
. Вы можете использовать это для преобразования подписанного целого числа в число, с которым вы работали с другими побитовыми операторами, в unsigned-integer-in-Number:
document.write(( (1<<31)>>>0 )+'<br />');
Тем:
document.write( (1 << 32) +"<br/>");
не будет работать, потому что все операции сдвига используют только самые младшие 5 бит сдвига (в JavaScript и других языках, подобных C). <<32
равно <<0
, т.е. без изменений.
Ответ 2
Используйте → > вместо → , чтобы получить сдвиг без знака вместо знакового. Все остальные побитовые операторы ведут себя одинаково независимо от того, подписаны ли ints.
Нарушение кода "когда подсеть... меньше 2". Похоже, что у вас может быть некоторая ошибка, не связанная с подписью целых чисел.
Ответ 3
Javascript не имеет целых чисел, все числа фактически удваиваются.
Ссылка Javascript 1.5 от Mozilla предполагает, что можно безопасно использовать побитовые операции для 32-разрядных чисел.
Ответ 4
Дуглас Крокфорд считает, что побитовые операторы являются одной из плохих частей javascript:
В Java побитовые операторы работают с целыми числами. JavaScript не имеет целых чисел. Он имеет только числа с плавающей запятой двойной точности. Таким образом, побитовые операторы преобразуют свои операнды чисел в целые числа, выполняют свою деятельность и затем конвертируют их обратно. В большинстве языков эти операторы очень близки к аппаратным средствам и очень быстры. В JavaScript они очень далеки от аппаратного обеспечения и очень медленны. JavaScript редко используется для выполнения манипуляций с битами.
- Дуглас Крокфорд в "JavaScript: хорошие детали", Приложение B, Побитовые операторы (выделено мной)
Вы уверены, что побитовые операторы действительно ускоряют вашу логику?
Ответ 5
Вот две функции, которые преобразуют адреса ipv4 в/из целых без знака в javascript:
function ip2long(ip) {
var ipl=0;
ip.split('.').forEach(function( octet ) {
ipl<<=8;
ipl+=parseInt(octet);
});
return(ipl >>>0);
}
function long2ip (ipl) {
return ( (ipl>>>24) +'.' +
(ipl>>16 & 255) +'.' +
(ipl>>8 & 255) +'.' +
(ipl & 255) );
}
Ответ 6
Какие у вас IP-адреса? IPv4 использует только 32-битные адреса, поэтому JavaScript должен быть хорошим (с использованием double, который дает 52-битную целую часть). IPv6 использует 128-битные адреса, поэтому вам придется использовать массив. Я предполагаю, что что-то еще сломано.
[EDIT] Создайте небольшую библиотеку, которая использует в качестве внутреннего типа данных массив из двух ints.