PHP

Как в PHP указать тип переменной unsigned int?

Проблема в том что на С++ и PHP два одинаковых кода возвращают разный результат.
//// С++
unsigned int A = 0xb7ec3d57;
unsigned int B = 0xb0000000;

A = A ^ (B >> 10);
A = A & ~B;

На выходе получаем A = 0x07ec3de7 (Как и должно быть)

////// PHP
$A = 0xb7ec3d57;
$B = 0xb0000000;

$A =$A ^ $B >> 10);
$A =$A & ~$B;

На выходе получаем A = 0x4813c2e7 (Как не должно быть)
Проблема в первом (знаковом бите) 32х битного числа 0xb7ec3d57 если указать меньшее число (так чтобы первый бит был 0) то результат будет одинаковый.
Есть ли решение этой проблемы на PHP?
Alex Bezverhi
Alex Bezverhi
148
http://php.net/manual/ru/language.operators.bitwise.php
Побитовый сдвиг в PHP - это арифметическая операция. Биты, сдвинутые за границы числа, отбрасываются. Сдвиг влево дополняет число нулями справа, сдвигая в то же время знаковый бит числа влево, что означает что знак операнда не сохраняется. Сдвиг вправо сохраняет копию сдвинутого знакового бита слева, что означает что знак операнда сохраняется.
Андрей Мартынов
Андрей Мартынов
67 252
Лучший ответ
Alex Bezverhi Действительно проблема именно со сдвигом, сейчас попробую исправить.
В PHP не существует беззнаковых типов данных. Основных вариантов 2:

1. После сдвига делать побитовое умножение на маску: (($B >> 10 ) & 0x3fffff)

2. Использовать 64-разрядный PHP - там 8-байные целые.
Керюха 456.к
Керюха 456.к
96 165
Попробуй отрицательные числа обрабатывать отдельно, убирая первый бит, потом сдвигая и возвращая бит в нужную ячейку.
А у меня выходит вообще 48003D57

$A = 0xb7ec3d57;
$B = 0xb0000000;

$A =$A ^ ($B >> 10);
$A =$A & ~$B;
echo dechex($A);

PHP вообще как-то странно делает сдвиг
B:
10110000000000000000000000000000
B >> 1
00101000000000000000000000000000

B:
1011000000000000000000000000
B >> 1
0101100000000000000000000000
сам удивился. проверил, и в правду.

unsigned int A = 0xb7ec3d57;
unsigned int B = 0xb0000000;

signed int siA = 0xb7ec3d57;
signed int siB = 0xb0000000;

A ^= B >> 10;
A &= ~B;

siA ^= siB >> 10;
siA &= ~siB;

printf("%08X\n", A);

printf("%08X\n", B);
printf("%08X\n", B >> 10);
printf("%08X\n", ~B);

printf("\n");

printf("%08X\n", siA);

printf("%08X\n", siB);
printf("%08X\n", siB >> 10);
printf("%08X\n", ~siB);

результат:

07C03D57
B0000000
002C0000
4FFFFFFF

48003D57
B0000000
FFEC0000
4FFFFFFF

видимо если right shift будет signed
то считается что за границами переменной еденицы?? где логика :)
Николай Саржан проблема решается ограничением по маске
(siB & 0xFFFFFFFF) >> 10