多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > php移位運算、移位操作學習筆記

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

來源:程序員人生   發布時間:2013-12-24 01:02:58 閱讀次數:3895次

位運算應用口訣

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

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

移位運算

要點

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

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

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

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

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

(1) 按位與-- &

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

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

(2) 按位或-- |

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

(3) 位異或-- ^

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

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

目 標           操 作              操作后狀態

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是奇數還是偶數          

a&1   = 0 偶數

a&1 =   1 奇數

(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型變量循環左移k次,即a=a<<k|a>>16-k   (設sizeof(int)=16)

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

(7)整數的平均值

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

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

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

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

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

  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)取模運算轉化成位運算 (在不產生溢出的情況下)

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

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

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

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

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 的 相反數 表示為 (~x+1)

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

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

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

>> 0xFFFFFFFFF

4294967295

>>  gettype(0xFFFFFFFF)

'double'

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

>> (int)0xFFFFFFFFF

-1

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

  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數學函數庫,直接處理字符串表示的整數,或者是GMP/BigInt擴展等。不過我想既然使用字符串,那么我可以字符串地徹底一些,把數字轉換成32個二進制的字符串,再手工填充0,最后轉換回來。

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

  1. <?php 
  2. /** 
  3.  * 無符號32位右移 
  4.  * @param mixed $x 要進行操作的數字,如果是字符串,必須是十進制形式 
  5.  * @param string $bits 右移位數 
  6.  * @return mixed 結果,如果超出整型范圍將返回浮點數 
  7.  */ 
  8. function shr32($x$bits){ 
  9.     // 位移量超出范圍的兩種情況 
  10.     if($bits <= 0){ 
  11.         return $x
  12.     } 
  13.     if($bits >= 32){ 
  14.         return 0; 
  15.     } 
  16.     //轉換成代表二進制數字的字符串 
  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.     //取出要移動的位數,并在左邊填充0 
  26.     return bindec(str_pad(substr($bin, 0, 32 - $bits), 32, '0', STR_PAD_LEFT)); 
  27. /** 
  28.  * 無符號32位左移 
  29.  * @param mixed $x 要進行操作的數字,如果是字符串,必須是十進制形式 
  30.  * @param string $bits 左移位數 
  31.  * @return mixed 結果,如果超出整型范圍將返回浮點數 
  32.  */  
  33. function shl32 ($x$bits){ 
  34.     // 位移量超出范圍的兩種情況 
  35.     if($bits <= 0){ 
  36.         return $x;  
  37.     } 
  38.     if($bits >= 32){ 
  39.         return 0;  
  40.     } 
  41.     //轉換成代表二進制數字的字符串 
  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.     //取出要移動的位數,并在右邊填充0 
  51.     return bindec(str_pad(substr($bin$bits), 32, '0', STR_PAD_RIGHT)); 
  52. ?> 
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 亚洲视频 在线观看 | 国产精品自拍在线 | 一级做a爰片性色毛片2021 | 日韩精品欧美激情国产一区 | 亚洲黄色影片 | 久久久国产精品免费看 | 可以免费观看的黄色网址 | 91成人爽a毛片一区二区 | 伊人官网 | 国产a v高清一区二区三区 | 最近的最新的中文字幕视频 | 亚洲国产一区二区三区在线观看 | 国产永久免费爽视频在线 | 秋霞特色aa大片在线观看 | 欧美一区二区视频 | 中文字幕第一页亚洲 | 亚洲精品欧美精品中文字幕 | 亚洲 欧美 综合 | 亚洲欧美一 | 日本 免费 高清 | 武则天一级淫片免费放 | 一区二区视频在线观看高清视频在线 | 女人18一级特级毛片免费看 | 亚洲精品资源在线 | 中文字幕一区二区三区四区五区 | 亚洲欧美日韩国产综合 | 亚洲免费a | 国产黄色免费在线观看 | 涩涩免费播放观看在线视频 | 黄色大片aa | 老女人一级全黄肉体毛片 | 国产一级鲁丝片 | 亚欧成人毛片一区二区三区四区 | 免费毛片二级c片观看动漫 免费毛片全部不收费的 | 欧美一级毛片图 | 日韩一级欧美一级在线观看 | 亚洲欧美日韩专区一 | 国产亚洲一区在线 | 高清欧美在线三级视频 | 日本一道本中文字幕 | 国产h肉在线视频免费观看 国产h视频 |