2011-01-26 71 views
2

我在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位數的值。

回答

0

如果你從數學角度思考這個問題,那就很有道理。 gmp_shiftr正在做-1/256,當向零舍入(gmp默認值)爲0時。

「>>」方法的工作原理與此相似,因爲負數用符號擴展二進制補碼形式表示。

+0

我也這麼認爲。然後我測試了它。 – 2011-01-26 01:16:05

1

望着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支持,您也許可以使 這項工作...