国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > PHP > 正文

php移位運算、移位操作學習筆記

2024-05-04 21:57:19
字體:
來源:轉載
供稿:網(wǎng)友

位運算應用口訣

清零取位要用與,某位置一可用或

若要取反和交換,輕輕松松用異或

移位運算

要點

1 它們都是雙目運算符,兩個運算分量都是整形,結果也是整形。

2 "<<" 左移:右邊空出的位上補0,左邊的位將從字頭擠掉,其值相當于乘2。

3 ">>"右移:右邊的位被擠掉。對于左邊移出的空位,如果是正數(shù)則空位補0,若為負數(shù),可能補0或補1,這取決于所用的計算機系統(tǒng)。

4 ">>>"運算符,右邊的位被擠掉,對于左邊移出的空位一概補上0。

位運算符的應用 (源操作數(shù)s 掩碼mask)

(1) 按位與-- &

1 清零特定位 (mask中特定位置0,其它位為1,s=s&mask)

2 取某數(shù)中指定位 (mask中特定位置1,其它位為0,s=s&mask)

(2) 按位或-- |

常用來將源操作數(shù)某些位置1,其它位不變。 (mask中特定位置1,其它位為0 s=s|mask)

(3) 位異或-- ^

1 使特定位的值取反 (mask中特定位置1,其它位為0 s=s^mask)

2 不引入第三變量,交換兩個變量的值 (設 a=a1,b=b1)

目 標           操 作              操作后狀態(tài)

a=a1^b1         a=a^b              a=a1^b1,b=b1

b=a1^b1^b1      b=a^b              a=a1^b1,b=a1

a=b1^a1^a1      a=a^b              a=b1,b=a1

二進制補碼運算公式:

-x = ~x + 1 = ~(x-1)

~x = -x-1

-(~x) = x+1

~(-x) = x-1

x+y = x - ~y - 1 = (x|y)+(x&y)

x-y = x + ~y + 1 = (x|~y)-(~x&y)

x^y = (x|y)-(x&y)

x|y = (x&~y)+y

x&y = (~x|y)-~x

x==y:    ~(x-y|y-x)

x!=y:    x-y|y-x

x< y:    (x-y)^((x^y)&((x-y)^x))

x<=y:    (x|~y)&((x^y)|~(y-x))

x< y:    (~x&y)|((~x|y)&(x-y))//無符號x,y比較

x<=y:    (~x|y)&((x^y)|~(y-x))//無符號x,y比較

應用舉例

(1) 判斷int型變量a是奇數(shù)還是偶數(shù)          

a&1   = 0 偶數(shù)

a&1 =   1 奇數(shù)

(2) 取int型變量a的第k位 (k=0,1,2……sizeof(int)),即a>>k&1

(3) 將int型變量a的第k位清0,即a=a&~(1<<k)

(4) 將int型變量a的第k位置1, 即a=a|(1<<k)

(5) int型變量循環(huán)左移k次,即a=a<<k|a>>16-k   (設sizeof(int)=16)

(6) int型變量a循環(huán)右移k次,即a=a>>k|a<<16-k   (設sizeof(int)=16)

(7)整數(shù)的平均值

對于兩個整數(shù)x,y,如果用 (x+y)/2 求平均值,會產(chǎn)生溢出,因為 x+y 可能會大于INT_MAX,但是我們知道它們的平均值是肯定不會溢出的,我們用如下算法:

  1. int average(int x, int y)   //返回X,Y 的平均值 
  2. {   
  3.      return (x&y)+((x^y)>>1); 

(8)判斷一個整數(shù)是不是2的冪,對于一個數(shù) x >= 0,判斷他是不是2的冪

  1. boolean power2(int x) 
  2.     return ((x&(x-1))==0)&&(x!=0); 

(9)不用temp交換兩個整數(shù)

  1. void swap(int x , int y) 
  2.     x ^= y; 
  3.     y ^= x; 
  4.     x ^= y; 

(10)計算絕對值

  1. int abs( int x ) 
  2. int y ; 
  3. y = x >> 31 ; 
  4. return (x^y)-y ;        //or: (x+y)^y 

(11)取模運算轉化成位運算 (在不產(chǎn)生溢出的情況下)

a % (2^n) 等價于 a & (2^n - 1)

(12)乘法運算轉化成位運算 (在不產(chǎn)生溢出的情況下)

a * (2^n) 等價于 a<< n

(13)除法運算轉化成位運算 (在不產(chǎn)生溢出的情況下)

a / (2^n) 等價于 a>> n  例: 12/8 == 12>>3

(14) a % 2 等價于 a & 1

(15) if (x == a) x= b;

else x= a;等價于 x= a ^ b ^ x;

(16) x 的 相反數(shù) 表示為 (~x+1)

最后補充一些關于二進制位移操作

PHP主要是設計于文本操作的,其實PHP不適合做數(shù)學運算,效率也不高,不過因為這次的項目中有個東西必須使用到二進制位移操作,在PHP上面遇到了一些麻煩。

因為PHP只有32位有符號整數(shù),沒有64位長整型,也沒有無符號整數(shù)。其整型的范圍是-231-1~231,超出這個范圍的,將被解釋為浮點數(shù)。因此,0xFFFFFFFF,直接打印,顯示的是4294967295,及232:

>> 0xFFFFFFFFF

4294967295

>>  gettype(0xFFFFFFFF)

'double'

而在32位有符號整型中,0xFFFFFFFF應表示-1:

>> (int)0xFFFFFFFFF

-1

而PHP不支持浮點數(shù)的二進制位移操作,如果要進行,會先轉換為整型,最后的結果,也將按照整型來返回:

  1. >> 1 << 31 
  2. -2147483648 
  3. >> 1 << 30 
  4. 1073741824 
  5. >> 1 << 32 
  6. >> 0xFFFFFFFF >> 1 
  7. -1 

同時PHP的向右位移操作,高位會填充符號位,而且PHP沒有提供類似Java的>>>來強制填充0:

  1. >> 1 << 32 
  2. >> 0xFFFFFFFF >> 1 
  3. -1 
  4. >> 0xFFFFFFFF >> 2 
  5. -1 
  6. >> 0xFFFFFFFF >> 3 
  7. -1 
  8. >> 0xFFFFFFFF >> 31 
  9. -1 

如何解決這個問題呢,我考慮過使用BCMath數(shù)學函數(shù)庫,直接處理字符串表示的整數(shù),或者是GMP/BigInt擴展等。不過我想既然使用字符串,那么我可以字符串地徹底一些,把數(shù)字轉換成32個二進制的字符串,再手工填充0,最后轉換回來。

不知道哪位有更好的方法,請告訴我,另外,其實代碼可以擴展為任意位2進制的位移操作,這里我沒有做,PHP代碼如下:

  1. <?php 
  2. /** 
  3.  * 無符號32位右移 
  4.  * @param mixed $x 要進行操作的數(shù)字,如果是字符串,必須是十進制形式 
  5.  * @param string $bits 右移位數(shù) 
  6.  * @return mixed 結果,如果超出整型范圍將返回浮點數(shù) 
  7.  */ 
  8. function shr32($x$bits){ 
  9.     // 位移量超出范圍的兩種情況 
  10.     if($bits <= 0){ 
  11.         return $x
  12.     } 
  13.     if($bits >= 32){ 
  14.         return 0; 
  15.     } 
  16.     //轉換成代表二進制數(shù)字的字符串 
  17.     $bin = decbin($x); 
  18.     $l = strlen($bin); 
  19.     //字符串長度超出則截取底32位,長度不夠,則填充高位為0到32位 
  20.     if($l > 32){ 
  21.         $bin = substr($bin$l - 32, 32); 
  22.     }elseif($l < 32){ 
  23.         $bin = str_pad($bin, 32, '0', STR_PAD_LEFT); 
  24.     } 
  25.     //取出要移動的位數(shù),并在左邊填充0 
  26.     return bindec(str_pad(substr($bin, 0, 32 - $bits), 32, '0', STR_PAD_LEFT)); 
  27. /** 
  28.  * 無符號32位左移 
  29.  * @param mixed $x 要進行操作的數(shù)字,如果是字符串,必須是十進制形式 
  30.  * @param string $bits 左移位數(shù) 
  31.  * @return mixed 結果,如果超出整型范圍將返回浮點數(shù) 
  32.  */  
  33. function shl32 ($x$bits){ 
  34.     // 位移量超出范圍的兩種情況 
  35.     if($bits <= 0){ 
  36.         return $x;  
  37.     } 
  38.     if($bits >= 32){ 
  39.         return 0;  
  40.     } 
  41.     //轉換成代表二進制數(shù)字的字符串 
  42.     $bin = decbin($x); 
  43.     $l = strlen($bin); 
  44.     //字符串長度超出則截取底32位,長度不夠,則填充高位為0到32位 
  45.     if($l > 32){ 
  46.         $bin = substr($bin$l - 32, 32); 
  47.     }elseif($l < 32){ 
  48.         $bin = str_pad($bin, 32, '0', STR_PAD_LEFT); 
  49.     } 
  50.     //取出要移動的位數(shù),并在右邊填充0 
  51.     return bindec(str_pad(substr($bin$bits), 32, '0', STR_PAD_RIGHT)); 
  52. ?> 

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 华宁县| 女性| 诸暨市| 深水埗区| 普格县| 舒兰市| 林州市| 道孚县| 达州市| 商南县| 临夏县| 镇宁| 中宁县| 开远市| 襄樊市| 盐城市| 印江| 嘉禾县| 淮南市| 郑州市| 黔南| 南陵县| 施秉县| 扬州市| 聊城市| 精河县| 桐城市| 罗山县| 云安县| 化隆| 太保市| 宝丰县| 虞城县| 华容县| 九龙坡区| 嘉荫县| 海宁市| 襄垣县| 陇川县| 辽中县| 古浪县|