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时。
“>>”方法的工作原理与此相似,因为负数用符号扩展二进制补码形式表示。
答
望着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支持,您也许可以使 这项工作...
我也这么认为。然后我测试了它。 – 2011-01-26 01:16:05