GMP位移不适用于负数

时间:2011-01-26 00:31:33

标签: php bit-manipulation bitwise-operators gmp

我在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) }?

或者,也许我可以根据它们的价值从负面结果中减去一些东西。?

我只想获得&gt;&gt;的值当我使用GMP时,它会给出&gt; 32位数字。

2 个答案:

答案 0 :(得分:1)

查看GMP documentation for the division routines,有一个功能

void mpz_tdiv_q_2exp (mpz_t q, mpz_t n, unsigned long int b)
似乎它可能是你想要的:一个对待的算术右移 n好像它是以二进制补码表示的,并且(我认为)将其移位b个位置 在右边。不幸的是,PHP的这个级别似乎没有被PHP GMP公开。

我找到了一个bit twiddling hack来进行符号扩展时的位数 在表示中是未知的:

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;

由于PHP GMP支持按位AND和XOR ,因此您可以制作 这项工作......

答案 1 :(得分:0)

如果你从数学角度思考它,那就有道理了。 gmp_shiftr正在执行-1/256,当向零舍入(gmp默认值)为0时。

“&gt;&gt;”方法的工作方式与此相同,因为负数以符号扩展的二进制补码形式表示。