Различные побитовые результаты работы на разных машинах

Я реализую простое вращение бит в PHP с помощью этого кода:

(($n>>1)&0xFFFFFFFF)|(($n&0x00000001)<<31)

Когда я запускаю этот код на разных машинах, я получаю совершенно разные результаты. Сначала я думал, что это как-то связано с порядком байтов, но они оба x86, я просто использую разные версии PHP.

Что вызывает такое поведение?

Изменить: не берите в голову мой предыдущий пример, это было неправильно

3

Решение

Проблема определенно вызвана тем, что PHP_INT_SIZE равен 4, а не 8

0

Другие решения

PHP 5.5 и 5.6 на x86-64 окнах является экспериментальным и использует 32-битную арифметику. Обойти это невозможно, поэтому нужно учитывать, что размер слова может варьироваться от 4 до 8 байт даже в одной архитектуре.

0

Вы можете изучить здесь шаг за шагом. Я сделал немного Скрипт 3v4l.org

Я проиллюстрировал два битовых вращения: 1-е для 2147483647, 2-е для 2147483648
1-е — максимальное 32-битное число, 2-е — еще одно

Увидеть: PHP: целые числа -Ручное # Целочисленное переполнение

Вы можете видеть, что вывод одинаков для каждой версии PHP от 4.3.0 и выше

Вот код:

<?php

$n = 2147483647;
shift($n);
echo "\n";
echo "\n";
echo "\n";
echo "\n";
$n = 2147483648;
shift($n);

function out($a, $b, $c, $b2 = '0', $c1 = ' ') {
$padstra = 40;
$padstrb = 23;
echo
str_pad($a, $padstra, ' ', STR_PAD_LEFT)
. " ". str_pad(decbin($b), 32, $b2, STR_PAD_LEFT)
. " ". str_pad($c, $padstrb, $c1) . "\n";
}

function shift($n) {
out($n    , $n , '$n'   );
echo "\n";
out('A:', $n >> 1 , '$n >> 1'   );
out('B:', 0xFFFFFFFF , '0xFFFFFFFF'   );
out('A & B:', ($n >> 1) & 0xFFFFFFFF , '($n >> 1) & 0xFFFFFFFF'   );
echo "\n";
out('C:', $n , '$n'   );
out('D:', 0x00000001 , '0x00000001'   );
out('C & D:', $n & 0x00000001 , '$n & 0x00000001'   );
echo "\n";
out('C & D:', $n & 0x00000001 , '$n & 0x00000001'   );
out('(C & D) << 31:', ($n & 0x00000001) << 31 , '($n & 0x00000001) << 31'   );
echo "\n";
out('A & B:', ($n >> 1) & 0xFFFFFFFF , '($n >> 1) & 0xFFFFFFFF'   );
out('(C & D) << 31:', ($n & 0x00000001) << 31 , '($n & 0x00000001) << 31'   );
out('(A & B) | ((C & D) << 31):', ($n >> 1) & 0xFFFFFFFF | ($n & 0x00000001) << 31 , '($n >> 1) & 0xFFFFFFFF | ($n & 0x00000001) << 31');
}

Вот вывод

                      2147483647 01111111111111111111111111111111 $n

A: 00111111111111111111111111111111 $n >> 1
B: 11111111111111111111111111111111 0xFFFFFFFF
A & B: 00111111111111111111111111111111 ($n >> 1) & 0xFFFFFFFF

C: 01111111111111111111111111111111 $n
D: 00000000000000000000000000000001 0x00000001
C & D: 00000000000000000000000000000001 $n & 0x00000001

C & D: 00000000000000000000000000000001 $n & 0x00000001
(C & D) << 31: 10000000000000000000000000000000 ($n & 0x00000001) << 31

A & B: 00111111111111111111111111111111 ($n >> 1) & 0xFFFFFFFF
(C & D) << 31: 10000000000000000000000000000000 ($n & 0x00000001) << 31
(A & B) | ((C & D) << 31): 10111111111111111111111111111111 ($n >> 1) & 0xFFFFFFFF | ($n & 0x00000001) << 31




2147483648 10000000000000000000000000000000 $n

A: 01000000000000000000000000000000 $n >> 1
B: 11111111111111111111111111111111 0xFFFFFFFF
A & B: 01000000000000000000000000000000 ($n >> 1) & 0xFFFFFFFF

C: 10000000000000000000000000000000 $n
D: 00000000000000000000000000000001 0x00000001
C & D: 00000000000000000000000000000000 $n & 0x00000001

C & D: 00000000000000000000000000000000 $n & 0x00000001
(C & D) << 31: 00000000000000000000000000000000 ($n & 0x00000001) << 31

A & B: 01000000000000000000000000000000 ($n >> 1) & 0xFFFFFFFF
(C & D) << 31: 00000000000000000000000000000000 ($n & 0x00000001) << 31
(A & B) | ((C & D) << 31): 01000000000000000000000000000000 ($n >> 1) & 0xFFFFFFFF | ($n & 0x00000001) << 31
0