了解 PHP &(与号、位与)运算符
Posted
技术标签:
【中文标题】了解 PHP &(与号、位与)运算符【英文标题】:Understanding PHP & (ampersand, bitwise and) operator 【发布时间】:2010-10-10 15:43:58 【问题描述】:我经常在我的代码中使用($var & 1)
,如果$var
是奇数则返回true,如果是偶数则返回false。
但是“&”实际上是做什么的呢?
【问题讨论】:
如果您能在 SO 上找到 any 编程问题的答案,岂不是很好?发生这种情况的唯一方法是,如果提出“简单”问题以及“谜题”问题。在此基础上,我认为这是一个有效的问题。 不要低估成功的程序员但不知道按位运算做什么的人数。这是一个有效的问题,透彻的理解有助于解释电路、加密和散列等的低级工作原理。 如果不知道在线手册在哪里,就无法编写 php。 “运营商”有一个明显的部分。 ... 不说不在手册中,但我当时找不到,现在也找不到。在提出关于 SO 的问题之前,我会尝试进行一定程度的尽职调查。如果您认为一个问题是不必要的,为什么要费劲呢?回答,投票否决或继续。 我在这里收到的答案质量(包括对二进制文件的详细解释)比我自己在 Google、PHP 文档和 SO 的 15 分钟研究中找到的要好得多。这就是使这个社区成为如此宝贵资源的原因。 【参考方案1】:二元系统的两个基本运算是 OR 和 AND。
OR 表示“如果 A 开启或 B 开启”。一个真实的例子是两个并联的开关。如果任一允许电流通过,则电流通过。
AND 表示“如果 A 和 B 都打开”。现实世界的例子是两个串联的开关。只有当两者都允许电流通过时,电流才会通过。
在计算机中,这些不是物理开关而是半导体,它们的功能称为logic gates。它们的作用与开关相同——对电流或无电流作出反应。
当应用于整数时,一个数字中的每一位都与另一个数字中的每一位相结合。因此,要理解按位运算符 OR 和 AND,您需要将数字转换为二进制,然后对每对匹配的位进行 OR 或 AND 运算。
这就是为什么:
00011011 (odd number)
AND
00000001 (& 1)
==
00000001 (results in 1)
而
00011010 (even number)
AND
00000001 (& 1)
==
00000000 (results in 0)
因此,(& 1) 操作使用 AND 逻辑将最右边的位与 1 进行比较。所有其他位都被有效地忽略了,因为任何东西都不是什么。二进制偶数也是十进制偶数(10是2的倍数)。
二进制系统的其他基本运算包括 NOT 和 XOR。 NOT 表示“如果 A 关闭”,并且是唯一一种只接受一个信号或“参数”而不是两个的逻辑门形式。 XOR 的意思是“如果 A 或 B 开启,但不是两者都开启”。然后是 NAND、NOR 和 NXOR,它们基本上只是不与 AND、OR 和 XOR 组合,即 NAND 表示“如果 A 和 B 不都打开”。
在编程中,运算符
& means AND,
| means OR,
~ means NOT, and
^ means XOR.
其他的可以组合起来,例如:
~ (a & b) is equivalent to a NAND operation
PHP 特定说明
位运算符不适用于浮点值,在 PHP 中浮点值将首先隐式转换为整数。超出可以表示为整数的范围的数字将被截断为零 - 也就是说,PHP_INT_MAX 上的所有数字在表达式($num & 1)
中看起来都是“偶数”。如果你想支持 PHP_INT_MIN/PHP_INT_MAX 之外的数字,你需要fmod($num, 2)
。 但是,如果您使用的是 64 位 PHP,那么您的整数将比浮点数具有更高的精度。
【讨论】:
我个人认为这比公认的答案更好地解释了这个问题,因为它实际上解释了按位运算在幕后的作用,这对于理解和使用它们至关重要。 【参考方案2】:这对于按位和 PHP 的了解也很有趣:
/**
* Regular
*/
echo (true && true); // 1
echo (true && false); // nothing
echo (true || false); // 1
echo (false || false); // nothing
echo (true xor false); // 1
echo (false xor false); // nothing
/**
* Bitwise
*/
echo (true & true); // 1
echo (true & false); // 0
echo (true | false); // 1
echo (false | false); // 0
echo (true ^ false); // 1
echo (false ^ false); // 0
【讨论】:
在我看来,这个答案并没有真正解释 && 与 & 的不同之处。 && 将两个参数都转换为布尔值,就像比较一个位一样。 & 以位方式进行比较:一个参数中的每个位都与另一个参数中的每个位进行比较。 "regular" 被称为逻辑和/或 了解位运算符如 & 和 | 也很重要对整数进行操作。此答案中的示例仅有效,因为true
转换为1
和false
转换为0
。如果你有echo ("cheese" & 4)
,它会输出零,而echo ("cheese" && 4)
会输出真。【参考方案3】:
除了其他答案,值得注意的是
if(func1() && func2())
如果func1()
返回真(“延迟评估”),则只会调用func2()
,而
if(func1() & func2())
无论如何都会调用这两个函数,但两者的真值表将是相同的(假设它们返回布尔值)。
thomasrutter 指出(在下面的 cmets 中)您可能不应该在实践中使用后者。 (A & B)
不一定具有与(A && B)
相同的真实性,特别是当A
和B
是整数时。例如,如果 A=1 且 B=2(均为真),则 A & B 将为假,而 A && B 为真。此外,另一位开发人员可能会认为这是一个拼写错误,并将其“更正”为两个与号。
【讨论】:
虽然这大部分时间都有效,但并不总是有效,例如当函数返回数字时。假设 func1() 返回 1,而 func2() 返回 4。func1() && func2()
的计算结果为 true
,而 func1() & func2()
的计算结果为 0
。即使在它确实有效的情况下,我也不会称其为良好的编码实践,因为它依赖于评估顺序和类型转换的副作用,使得阅读和理解代码的目的变得更加困难。任何审查代码的人都可能认为这是一个错字。【参考方案4】:
我知道您的问题是关于理解按位运算符,并且接受的答案很好地解释了它。但是对于您给出的示例,我不禁建议您改用模运算符:
($var % 2) /* instead of */ ($var & 1)
因为它清楚地表明您正在检查数字是否为奇数(不能被 2 整除),并且它更通用,因此您可以以相同的方式使用 ($var % 3) 并推断它是如何工作的任何 N。
【讨论】:
【参考方案5】:& 是二进制 and
。如果你有一个二进制值,而你 and
有另一个二进制值,那么结果将是两者的按位 and
。一个例子:
01101010
& 01011001
= 01001000
最右边的位要么是 1(在这种情况下是奇数),要么是 0,在这种情况下是偶数。如果您&
一个数字为 1,您只查看最低有效位,并且 if 检查该数字是 1 还是 0。正如其他人所提到的,查看位运算符以了解它们如何工作的信息。
【讨论】:
你能举出一堆有用的例子吗?因为奇数甚至偶数都可以使用模数,对。说$is_even = $x % 2 === 0; $is_odd = !$is_even;
更容易理解和阅读以上是关于了解 PHP &(与号、位与)运算符的主要内容,如果未能解决你的问题,请参考以下文章