【问题标题】:Bitwise operations on boolean values布尔值的按位运算
【发布时间】:2014-09-16 18:13:51
【问题描述】:

据我所知,按位运算符会检查所有相应的位,如下所示:

echo 64 | 32;   //prints 96
echo 'a' & 'b'; //prints `

虽然条件 &&|| 运算符对布尔值执行操作:

echo (int)(true && false); //prints: 0
echo (int)(true || false); //prints: 1

当我(在我的脑海中)想要预测按位运算的结果时,我首先将值转换为它们的二进制表示形式(这取决于数据类型)。在此之后,我逐位比较它,并将结果转换为合适的输出类型(我想这是由操作数决定的)。虽然在某一时刻,我尝试对布尔值做同样的事情,它(据我所知)只包含内存中的一位,使true对应于1₂,并使false对应于0₂(在二进制)。因此,对这些值执行按位运算应该会产生与&&|| 类似的结果,对吧?向您展示我的意思:

true & false    =>      1₂ & 0₂      =>      0₂     =>     false
true | false    =>      1₂ | 0₂      =>      1₂     =>     true
~true           =>      ~1₂          =>      0₂     =>     false

(不包括xor,因为没有对应的条件布尔运算符。)

在我看来,这种行为应该真的等同于条件运算符:

true && false   =>      false
true || false   =>      true
!true           =>      false

因此,我设置了这段代码来测试它:

    echo "true AND false: " . ((true && false) ? "1" : "0") . "<br />\n";
    echo "true OR false: " . ((true || false) ? "1" : "0") . "<br />\n";
    echo "NOT true: " . ((!true) ? "1" : "0") . "<br />\n";

    echo "<br />\n";

    echo "true BITAND false: " . ((true & false) ? "1" : "0") . "<br />\n";
    echo "true BITOR false: " . ((true | false) ? "1" : "0") . "<br />\n";
    echo "BITNOT true: " . ((~true) ? "1" : "0") . "<br />\n";

它给了我以下输出:

真假:0
真或假:1
不正确:0

真 BITAND 假:0
真比特假:1

致命错误:第 21 行的 C:\Abyss Web Server\htdocs\handler.php 中不支持的操作数类型

因此,我有两个问题:

  1. 如果我们(看起来)可以在布尔值上使用&amp;|,那么&amp;&amp;|| 有什么意义?
  2. 为什么我不能~true(或者换句话说,为什么不支持布尔值)?对我来说,~true 返回false 听起来合乎逻辑。

我确实想出了一件事,那就是 &amp;&amp;|| 将(有时)将值转换为 bool,然后返回正确的结果,如果我们(错误地)碰巧传递了一个值那不是bool 的类型。但是要解决这个问题,我们不能先做一个演员表吗?如:

if ((bool)$foo & (bool)$bar) { ...

感觉就像我在这里错过了一个改变一切的重要部分......但以防万一我没有,我尽可能多地提供信息。有人可以通过回答我的两个问题让我更好地理解这一点吗?在这一点上我很困惑,我已经考虑了很长时间。

【问题讨论】:

  • 位运算符不返回布尔值,除非它们对布尔值进行运算,比较运算符总是返回布尔结果......这是一个非常重要的区别
  • 两个整数值的位运算符将返回一个整数值...例如(使用 8 位简化)00001000 | 00000111 将返回 0000111100001111 & 01010101 将返回 00000101
  • @Mark Ba​​ker 确实如此,尽管这就是为什么我假设在某处显式强制转换是合适的(就像在我的上一个示例中一样)。我的意思是,如果条件运算符(或比较运算符)有 2 个不同的值,他们需要先转换它们,对吗?那么无论运营商如何,都不会进行演员阵容吗?或者我提供的最后一个代码还有其他弱点吗? (换句话说,87 不是这样转换的:(bool)8 | (bool)7,即使我们使用8 || 7?)
  • 当 PHP 将对布尔值进行隐式强制转换时,为什么会有显式强制转换的开销......并且一旦值为布尔值,比较可能比按位运算更快
  • 嗯 PHP 是开源的,所以你可以随时查看源代码......但是这两种类型的运算符是为非常不同的目的而设计的......按位运算符适用于布尔值,但它们的力量正在处理非布尔值......并且因为 PHP 是松散类型的,比较运算符旨在处理任何数据类型......并且两种类型的运算符的行为都有很好的记录

标签: php bit-manipulation bitwise-operators


【解决方案1】:

回答 1

部分布尔表达式(||&amp;&amp;!、...)仅在需要时进行评估(从左到右):

  if ($a | func()) { } // func is always called
  if ($a || func()) { } // func is not called if $a is true,
                        // because expression is true whatever func will return
  if ($a && func()) { } // func is not called if $a is false,
                        // because expression is false whatever func will return
  func() || exit(); // exit() will be called if func() returns false

查看文档:http://php.net/manual/en/language.operators.logical.php

回答 2

~true 似乎没有意义:true0x00...01~true 将是 0xff...fe 而不是 false 0x000...0

var_dump(~((int)true)); // prints: int(-2)
echo dechex(~((int)true)); // prints: fffffffffffffffe

改用!-operator:

var_dump(!true); // prints: bool(false)

简历

仅当您需要更改位时才使用位运算符。

【讨论】:

  • 感谢您的回答,但还有一件事我不明白:为什么~true0x00...01 相同,而不是0x0?布尔值的大小不是 1 位吗?除此之外,第一个问题的答案似乎很好,非常感谢。
  • 不要问我为什么我又一次偶然发现了这个,但我又读了一遍(出于兴趣)并意识到我理解了我以前不理解的东西。如果有人对此感兴趣(我对此表示怀疑),我将总结一下: 与内存架构相关的单比特变量似乎还有其他困难(它们太小了,而且 RAM 不是为处理它们而设计的) .这就解释了为什么布尔值占用更多空间以及为什么在操作两个布尔值时 bitNOT 不会产生相同的结果。 (我会接受这个答案,因为我上次忘记这样做了。)
【解决方案2】:

truefalse 布尔标志,尽管作为 32 位或 64 位值存储在内存中,但应被视为两种状态的布尔值。你最终只会在护臂上使用它,所以你不应该对它们进行算术运算。 &amp;&amp;|| 计算为布尔标志、位运算符 & 和 |计算结果与操作数相同(例如,int &amp; int 计算结果为 intint &amp;&amp; int 计算结果为布尔值)。

故事是: 当您必须对某些条件做出决定时,请使用 &amp;&amp;||。使用&amp;| 对值执行布尔运算。

那是 C++

C 没有任何内置布尔值,因此任何非零值都是true,零是false

【讨论】:

  • 谢谢,但我不太明白这一点:“真假布尔标志,尽管作为 32 位或 64 位值存储在内存中,但应该被视为两种状态的布尔值值。”。
  • 这意味着您不应该对它们进行数学运算(例如,将布尔值转换为 int,然后使用其他变量对其进行位掩码)
  • 按位运算符不是对位本身进行操作吗?我不知道它需要强制转换,而且我不太明白您所说的数学是什么意思。换句话说,true &amp; true 会结束任何演员阵容吗?
猜你喜欢
  • 1970-01-01
  • 2010-12-16
  • 2015-10-22
  • 1970-01-01
  • 2011-04-20
  • 1970-01-01
  • 1970-01-01
  • 2015-09-24
  • 2013-03-02
相关资源
最近更新 更多