Сдвиг битов GMP не работает с отрицательными числами - PullRequest
2 голосов
/ 26 января 2011

Я нашел эту функцию на php.net. Кажется, он работает на положительных числах, но не на отрицательных:

function gmp_shiftr($x,$n) { // shift right
  return(gmp_div($x,gmp_pow(2,$n)));
} 

echo -1 >> 8; //returns -1, presumably correctly
echo "<br />";
echo gmp_strval(gmp_shiftr(-1,8)); //returns 0, presumably incorrectly

Как настроить функцию работы с негативами?

У меня есть две идеи:

Может быть, я мог бы сделать что-то вроде

if (whatever) { $a >> $b} else{ gmp_shiftr($a, $b) }?

Или, может быть, я мог бы вычесть что-то из отрицательных результатов в зависимости от их значения ..?

Я просто хочу получить значение, которое >> даст, но также получить его для> 32-разрядных чисел, когда я использую GMP.

Ответы [ 2 ]

1 голос
/ 26 января 2011

Глядя на документацию GMP для подпрограмм разделения , есть функция

void mpz_tdiv_q_2exp (mpz_t q, mpz_t n, unsigned long int b)

кажется, что это может быть то, что вы хотите: арифметический сдвиг вправо, который лечит n, как если бы оно было представлено в двух дополнениях, и (я думаю) сдвигает его b мест направо. К сожалению, этот уровень API, похоже, не раскрывается PHP GMP.

Я нашел битовый хакерский взлом для выполнения расширения знака при количестве бит в представлении неизвестно:

unsigned b; // number of bits representing the number in x
int x;      // sign extend this b-bit number to r
int r;      // resulting sign-extended number
int const m = 1U << (b - 1); // mask can be pre-computed if b is fixed

x = x & ((1U << b) - 1);  // (Skip this if bits in x above position b are already zero.)
r = (x ^ m) - m;

Так как битовые AND и XOR поддерживаются PHP GMP, вы можете сделать эта работа ...

0 голосов
/ 26 января 2011

Если вы думаете об этом математически, это имеет смысл.gmp_shiftr выполняет -1/256, что при округлении до нуля (значение gmp по умолчанию) равно 0.

Метод ">>" работает так же, как и он, потому что отрицательные числа представлены в виде дополнения знака со знаком двойного расширения,

...