php實現求二進制中1的個數(右移、&、int32位)(n = n & (n - 1);)
一、總結
1、PHP中的位運算符和java和c++一樣
2、位移運算符看箭頭方向,箭頭向左就是左移,左移*2
3、php中整形32位
二、php實現求二進制中1的個數
題目描述:
輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼表示。
最佳代碼:
絕對最佳答案及分析:
1 public classSolution {2 public int NumberOf1(intn) {3 int count = 0;4 while(n!= 0){5 count++;6 n = n & (n - 1);7 }8 returncount;9 }10 }
答案正確:恭喜!您提交的程序通過了所有的測試用例
分析一下代碼: 這段小小的代碼,很是巧妙。
如果一個整數不為0,那么這個整數至少有一位是1。如果我們把這個整數減1,那么原來處在整數最右邊的1就會變為0,原來在1后面的所有的0都會變成1(如果最右邊的1后面還有0的話)。其余所有位將不會受到影響。
舉個例子:一個二進制數1100,從右邊數起第三位是處於最右邊的一個1。減去1后,第三位變成0,它后面的兩位0變成了1,而前面的1保持不變,因此得到的結果是1011.我們發現減1的結果是把最右邊的一個1開始的所有位都取反了。這個時候如果我們再把原來的整數和減去1之后的結果做與運算,從原來整數最右邊一個1那一位開始所有位都會變成0。如1100&1011=1000.也就是說,把一個整數減去1,再和原整數做與運算,會把該整數最右邊一個1變成0.那么一個整數的二進制有多少個1,就可以進行多少次這樣的操作。
代碼:
1 <?php2
3 function NumberOf1($n)4 {5 $count = 0;6 for($i = 0;$i <32;$i++){ //3、php中整形32位7 if(($n >> $i) & 1){ //1、PHP中的位運算符和java和c++一樣 2、位移運算符看箭頭方向,箭頭向左就是左移,左移*28 $count++;9 }10 }11 return $count;12 }
三、拓展-php位運算符
位運算符¶
位運算符允許對整型數中指定的位進行求值和操作。
位運算符
例子
名稱
結果
$a & $b
And(按位與)
將把 $a 和 $b 中都為 1 的位設為 1。
$a | $b
Or(按位或)
將把 $a 和 $b 中任何一個為 1 的位設為 1。
$a ^ $b
Xor(按位異或)
將把 $a 和 $b 中一個為 1 另一個為 0 的位設為 1。
~ $a
Not(按位取反)
將 $a 中為 0 的位設為 1,反之亦然。
$a << $b
Shift left(左移)
將 $a 中的位向左移動 $b 次(每一次移動都表示“乘以 2”)。
$a >> $b
Shift right(右移)
將 $a 中的位向右移動 $b 次(每一次移動都表示“除以 2”)。
位移在 PHP 中是數學運算。向任何方向移出去的位都被丟棄。左移時右側以零填充,符號位被移走意味着正負號不被保留。右移時左側以符號位填充,意味着正負號被保留。
要用括號確保想要的優先級。例如 $a & $b == true 先進行比較再進行按位與;而 ($a & $b) == true 則先進行按位與再進行比較。
If both operands for the &, | and ^ operators are strings, then the operation will be performed on the ASCII values of the characters that make up the strings and the result will be a string. In all other cases, both operands will be converted to integers and the result will be an integer.
If the operand for the ~ operator is a string, the operation will be performed on the ASCII values of the characters that make up the string and the result will be a string, otherwise the operand and the result will be treated as integers.
Both operands and the result for the <> operators are always treated as integers.
PHP 的 ini 設定 error_reporting 使用了按位的值,
提供了關閉某個位的真實例子。要顯示除了提示級別
之外的所有錯誤,php.ini 中是這樣用的:
E_ALL & ~E_NOTICE
具體運作方式是先取得 E_ALL 的值:
00000000000000000111011111111111
再取得 E_NOTICE 的值:
00000000000000000000000000001000 然后通過 ~ 將其取反: 11111111111111111111111111110111 最后再用按位與 AND(&)得到兩個值中都設定了(為 1)的位: 00000000000000000111011111110111
另外一個方法是用按位異或 XOR(^)來取得只在
其中一個值中設定了的位:
E_ALL ^ E_NOTICE
error_reporting 也可用來演示怎樣置位。只顯示錯誤和可恢復
錯誤的方法是:
E_ERROR | E_RECOVERABLE_ERROR
也就是將 E_ERROR
00000000000000000000000000000001
和 E_RECOVERABLE_ERROR
00000000000000000001000000000000 用按位或 OR(|)運算符來取得在任何一個值中被置位的結果: 00000000000000000001000000000001
Example #1 整數的 AND,OR 和 XOR 位運算符
/*
* Ignore the top section,
* it is just formatting to make output clearer.
*/
$format = '(%1$2d = %1$04b) = (%2$2d = %2$04b)'
. ' %3$s (%4$2d = %4$04b)' . "\n";
echo <<
--------- --------- -- ---------
result value op test
--------- --------- -- ---------
EOH;
/*
* Here are the examples.
*/
$values = array(0, 1, 2, 4, 8);
$test = 1 + 4;
echo "\n Bitwise AND \n";
foreach ($values as $value) {
$result = $value & $test;
printf($format, $result, $value, '&', $test);
}
echo "\n Bitwise Inclusive OR \n";
foreach ($values as $value) {
$result = $value | $test;
printf($format, $result, $value, '|', $test);
}
echo "\n Bitwise Exclusive OR (XOR) \n";
foreach ($values as $value) {
$result = $value ^ $test;
printf($format, $result, $value, '^', $test);
}
?>
以上例程會輸出:
--------- --------- -- ---------
result value op test
--------- --------- -- ---------
Bitwise AND
( 0 = 0000) = ( 0 = 0000) & ( 5 = 0101)
( 1 = 0001) = ( 1 = 0001) & ( 5 = 0101)
( 0 = 0000) = ( 2 = 0010) & ( 5 = 0101)
( 4 = 0100) = ( 4 = 0100) & ( 5 = 0101)
( 0 = 0000) = ( 8 = 1000) & ( 5 = 0101)
Bitwise Inclusive OR
( 5 = 0101) = ( 0 = 0000) | ( 5 = 0101)
( 5 = 0101) = ( 1 = 0001) | ( 5 = 0101)
( 7 = 0111) = ( 2 = 0010) | ( 5 = 0101)
( 5 = 0101) = ( 4 = 0100) | ( 5 = 0101)
(13 = 1101) = ( 8 = 1000) | ( 5 = 0101)
Bitwise Exclusive OR (XOR)
( 5 = 0101) = ( 0 = 0000) ^ ( 5 = 0101)
( 4 = 0100) = ( 1 = 0001) ^ ( 5 = 0101)
( 7 = 0111) = ( 2 = 0010) ^ ( 5 = 0101)
( 1 = 0001) = ( 4 = 0100) ^ ( 5 = 0101)
(13 = 1101) = ( 8 = 1000) ^ ( 5 = 0101)
Example #2 字符串的 XOR 運算符
echo 12 ^ 9; // Outputs '5'
echo "12" ^ "9"; // Outputs the Backspace character (ascii 8)
// ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8
echo "hallo" ^ "hello"; // Outputs the ascii values #0 #4 #0 #0 #0
// 'a' ^ 'e' = #4
echo 2 ^ "3"; // Outputs 1
// 2 ^ ((int)"3") == 1
echo "2" ^ 3; // Outputs 1
// ((int)"2") ^ 3 == 1
?>
Example #3 整數的位移
/*
* Here are the examples.
*/
echo "\n--- BIT SHIFT RIGHT ON POSITIVE INTEGERS ---\n";
$val = 4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copy of sign bit shifted into left side');
$val = 4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places);
$val = 4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'bits shift out right side');
$val = 4;
$places = 4;
$res = $val >> $places;
p($res, $val, '>>', $places, 'same result as above; can not shift beyond 0');
echo "\n--- BIT SHIFT RIGHT ON NEGATIVE INTEGERS ---\n";
$val = -4;
$places = 1;
$res = $val >> $places;
p($res, $val, '>>', $places, 'copy of sign bit shifted into left side');
$val = -4;
$places = 2;
$res = $val >> $places;
p($res, $val, '>>', $places, 'bits shift out right side');
$val = -4;
$places = 3;
$res = $val >> $places;
p($res, $val, '>>', $places, 'same result as above; can not shift beyond -1');
echo "\n--- BIT SHIFT LEFT ON POSITIVE INTEGERS ---\n";
$val = 4;
$places = 1;
$res = $val <
p($res, $val, '<
$val = 4;
$places = (PHP_INT_SIZE * 8) - 4;
$res = $val <
p($res, $val, '<
$val = 4;
$places = (PHP_INT_SIZE * 8) - 3;
$res = $val <
p($res, $val, '<
$val = 4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val <
p($res, $val, '<
echo "\n--- BIT SHIFT LEFT ON NEGATIVE INTEGERS ---\n";
$val = -4;
$places = 1;
$res = $val <
p($res, $val, '<
$val = -4;
$places = (PHP_INT_SIZE * 8) - 3;
$res = $val <
p($res, $val, '<
$val = -4;
$places = (PHP_INT_SIZE * 8) - 2;
$res = $val <
p($res, $val, '<
/*
* Ignore this bottom section,
* it is just formatting to make output clearer.
*/
function p($res, $val, $op, $places, $note = '') {
$format = '%0' . (PHP_INT_SIZE * 8) . "b\n";
printf("Expression: %d = %d %s %d\n", $res, $val, $op, $places);
echo " Decimal:\n";
printf(" val=%d\n", $val);
printf(" res=%d\n", $res);
echo " Binary:\n";
printf(' val=' . $format, $val);
printf(' res=' . $format, $res);
if ($note) {
echo " NOTE: $note\n";
}
echo "\n";
}
?>