GMP位移对负数不起作用

问题描述:

我在php.net上找到了这个函数。它似乎在正数上工作,但在负数上失败:GMP位移对负数不起作用

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

或者线条,也许我可以减去负的成绩东西..?

我只想得到>>会给出的值,但是当我使用GMP时也会得到大于32位数的值。

如果你从数学角度思考这个问题,那就很有道理。 gmp_shiftr正在做-1/256,当向零舍入(gmp默认值)为0时。

“>>”方法的工作原理与此相似,因为负数用符号扩展二进制补码形式表示。

+0

我也这么认为。然后我测试了它。 – 2011-01-26 01:16:05

望着GMP documentation for the division routines,有一个功能

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

,似乎像它可能是你想要的:即把 n就好像它是在二进制补码表示的算术右移,和(我认为)转移它b地方 在右边。不幸的是,该级别的API似乎没有被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; 

由于按位AND和XOR 由PHP GMP支持,您也许可以使 这项工作...