Функция незаписанного сдвига вправо не работает для отрицательного входа

Я ищу способ использовать функцию >>> из JavaScript в 64-разрядной версии PHP 5.5.14. Я нашел эту функцию в своем googling:

 function uRShift($a, $b) { $z = hexdec(80000000); if ($z & $a) { $a = ($a >> 1); $a &= (~$z); $a |= 0x40000000; $a = ($a >> ($b - 1)); } else { $a = ($a >> $b); } return $a; } 

Эта функция работает нормально для положительных чисел, но я получаю разные результаты при прохождении отрицательных чисел.

Например:

PHP:

 In: echo uRShift(-672461345, 25); Out: -149 

JavaScript (Chrome 35):

 In: -672461345 >>> 25 Out: 107 

РЕДАКТИРОВАТЬ:

Я также попробовал другую функцию, указанную в ответе, указанном выше.

 function uRShift($a, $b) { if($b == 0) return $a; return ($a >> $b) & ~(1<<(8*PHP_INT_SIZE-1)>>($b-1)); } 

PHP:

 In: echo uRShift(-672461345, 25); Out: 549755813867 

Runnable

Константа 0x80000000 (она написана как вызов hexdec и хранится в переменной $z в этом примере) представляет собой отрицательное целое число с отрицательным hexdec ( 100000.... в двоичном формате). Выражение ~$z должно давать побитовое NOT этого, а именно наивысшее положительное целое число (которое заканчивается 2147483647 ).

Исходный номер ( положительный 0x80000000 , то есть 2147483648 ) не может быть сохранен в виде 32-битного целого числа, поэтому обычно он будет храниться как поплавок какого-либо типа. К сожалению, PHP 5.5 считает, что ~(2147483648) равно -2147483649 , что было бы правильно, если бы мы имели дело, например, с 64-битными целыми числами .

И действительно, повторение PHP_INT_SIZE в runnable указывает, что целые числа составляют 8 байтов, что составляет 64 бита. Таким образом, арифметика не работает прямо в PHP 5.5.

Чтобы исправить это, просто замените ~$z статической константой следующим образом:

 function uRShift($a, $b) { if ($a < 0) { $a = ($a >> 1); $a &= 2147483647; $a |= 0x40000000; $a = ($a >> ($b - 1)); } else { $a = ($a >> $b); } return $a; } 

Эта функция по-прежнему имеет некоторые недостатки; например, смещение на 0 не работает должным образом.