【问题标题】:What does Xor -> And -> Xor do?Xor -> And -> Xor 做什么?
【发布时间】:2012-10-01 12:08:40
【问题描述】:

我的算法有问题。

我有一个用于 IO 的字节,其中某些位可以使用称为 XorAndXor 的方法设置。 该算法的工作原理如下:

newValue = (((currentValue XOR xorMask1) AND andMask) XOR xorMask2)

描述如下:

如果两个异或掩码具有相同的值,则此函数插入 xor-mask 的位到 and-mask 所在的位位置 1.其他位保持不变。

所以我对这个函数的期望是当我有以下字节时:00101101 并且我将01000000 用于 xor-masks 和 and-mask,只有第二个位将设置为 1 和结果将是01101101

但是,在进行数学运算并遍历函数时,结果是 00000000

我做错了什么,或者这个功能有什么我不明白的地方?这种底层编程已经有一段时间了,所以我真的不知道这是否是一种经常使用的方法,以及为什么以及如何使用它。

让我问一个简单的问题:有没有办法有效地使用这个函数来设置(或取消设置/更改)单个位(无需专门询问当前值)? p>

例如:当前值为00101101(这个我不知道),但我只是想确保第二位被设置,所以结果一定是01101101 .

重要信息在我的文档 PDF 中,XOR 和第一个 xorMask1 之间似乎有一点空间,所以这可能是 ~! 或其他一些否定符号的位置由于一些奇怪的编码问题,它很可能会丢失。因此,我将测试该函数是否符合文档所述或函数声明所述。抓紧你的头盔,将返回结果(请鼓)....

【问题讨论】:

  • 我承认我有点不知所措,想着如何用位运算符检查掩码(不是单个位,而是整个掩码)的相等性。
  • 好吧,我只想提交两次相同的掩码,所以如果我想将第 2 位设置为 1,我将输入 01000000 作为 mask1 和 mask2。
  • 好吧,答案很少,问题不是我不知道 XOR 和 AND 做什么,只是我很难弄清楚函数想要什么。这就是为什么我要问这是否是某种经常使用的行为。
  • 我认为应该是 ~andMask 而不是 andMask - 请参阅下面的答案

标签: c++ bitwise-operators


【解决方案1】:
     00101101 
XOR  01000000
-------------
     01101101
AND  01000000
-------------
     01000000 
XOR  01000000
-------------
     00000000

文档不正确。这不是我第一次看到完全偏离初始实现的实现,但没有人费心更新文档。

我做了一个快速检查,所以我可能错了,但以下内容与文档一致:

newValue = (((currentValue XOR xorMask1) AND ~andMask) XOR xorMask2)

     00101101 
XOR  01100100
-------------
     01001001
AND  10011011
-------------
     00001001 
XOR  01100100
-------------
     01101101

这是表达式New = Curr XOR Xor1 AND ~And XOR Xor2的逻辑表,其中Xor1 == Xor2

CURR: 0 1 0 1   0 1 0 1 
XOR1: 0 0 1 1   0 0 1 1
AND:  0 0 0 0   1 1 1 1 
XOR2: 0 0 1 1   0 0 1 1 
-----------------------
NEW:  0 1 0 1   0 0 1 1 
      ---v---   ---v---
      same as   same as  
      current   xor mask
      where     where
      AND = 0   AND = 1

【讨论】:

  • 您的第二段代码根本没有使用xorMask2。我认为“如果两个 xor-masks 具有相同的值”可以解释为两个不同的东西,但这些都不是,“xorMask2 的值是完全不相关的”:-)
  • 你是对的:)。但是,这并不是为了澄清文档,这令人困惑,而是更多地考虑如何获得这样的结果
  • +1 对于这个答案,因为我也认为这是不正确的文档(该行 - This function reads the performs the function - 也是对此的有力论据))。毕竟,如果检查了它们的相等性,则无需在公式中使用这两个掩码。
  • 现在(倒置)我对此表示怀疑。如果这里的两个掩码都是0,会发生什么? newValue = currentValue AND ~andMask 不应该是答案。
  • 似乎一致:inserts the bits of the xor-mask into the bit locations where the and-mask is 1. The other bits remain unchanged。由于 AND 掩码为 0,因此不插入任何内容,即所有位保持不变。
【解决方案2】:

我已经研究了一段时间了,我想我看到了其他人看不到的东西。 XOR AND XOR 过程对于设置多个字节而不干扰其他字节很有用。例如,我们有一个给定的字节,我们希望将其设置为 1x1x xxx0,其中 x 是我们不关心的值。使用 XOR AND XOR 过程,我们使用以下掩码来打开和关闭我们不关心的位。我们使用 XOR 掩码打开位,使用 AND 掩码关闭位,我们不关心我们保留默认值的掩码(0 表示 XOR 掩码 [x XOR 0 = x] 和 1对于 AND 掩码 [x AND 1 = x])。所以给定我们想要的值,我们的掩码看起来像这样:

XOR: 10100000
AND: 01011110

如果我们的神秘位是 10010101,那么数学如下:

10010101
10100000 XOR
00110101 =
01011110 AND
00010100 =
10100000 XOR
10110100 =

我们想要打开的位是打开的,我们想要关闭的位是关闭的,无论它们之前的状态如何。

这是管理多个位的一个很好的逻辑。

编辑:最后一个 XOR 用于切换。如果您知道有一点需要更改,但不是什么,请将其设为 1。假设我们要切换第三位,或者掩码将是:

XOR1 10100000
AND  01011110
XOR2 10100100

最后一次交互将变为

00010100 =
10100100 XOR
10110000 =

第三位被切换。

【讨论】:

    【解决方案3】:

    要回答您非常简单的问题,这是如何设置的:

    value |=  0x100;  
    

    这是清除一点的方法:

    value &= ~0x100;
    

    在这个例子中,0x100 是二进制的000100000000,所以它设置/清除第 8 位(从右数)。

    其他人已经指出您的代码示例没有按照它声称的那样做,所以我不会进一步详细说明。

    【讨论】:

      【解决方案4】:

      XOR 是二进制互斥的,只有当一个或另一个位设置为 1 时才会返回 true,因此:

      00101101 XOR 01000000 = 01101101
      01101101 AND 01000000 = 01000000
      01000000 XOR 01000000 = 00000000
      

      【讨论】:

        【解决方案5】:
        p|q|r|s|p^q|(p^q)&r|((p^q)&r)^s|
        0|0|0|0| 0 |   0   |     0     |
        0|0|0|1| 0 |   0   |     1     |
        0|0|1|0| 0 |   0   |     0     |
        0|0|1|1| 0 |   0   |     1     |
        0|1|0|0| 1 |   0   |     0     |
        0|1|0|1| 1 |   0   |     1     |
        0|1|1|0| 1 |   1   |     1     |
        0|1|1|1| 1 |   1   |     0     |
        1|0|0|0| 1 |   0   |     0     |
        1|0|0|1| 1 |   0   |     1     |
        1|0|1|0| 1 |   1   |     1     |
        1|0|1|1| 1 |   1   |     0     |
        1|1|0|0| 0 |   0   |     0     |
        1|1|0|1| 0 |   0   |     1     |
        1|1|1|0| 0 |   0   |     0     |
        1|1|1|1| 0 |   0   |     1     |
        

        检查此表以获取位的输入值,以检查输出。相应地更改您的掩码,以满足您的输出需求。

        【讨论】:

          【解决方案6】:

          让自己成为一个真值表,并在整个过程中遵循 1 和 0。

          • 任何 Xor 0 都将保持不变(1 Xor 0 为 1;0 Xor 0 为 0)
          • 任何异或 1 都会被翻转(1 异或 1 为 0;0 异或 1 为 1)
          • 当 Anding 时,所有内容都变为 0,除了 And 掩码中有 1 位 - 那些保持不变

          所以你的第一个异或只能改变左边的第二位,因为那是你在掩码中有一个 1 的地方。它将那个位从 0 翻转到 1。And 不理会那个位,并将所有其他位设置为 0。第二个 Xor 将您的 1 翻转回 0 并保持所有其他位不变。

          结果:如你所说,全为零。

          你的问题是 Xor 和 And 的组合会给你文档所说的行为吗?要仅打开一位,请使用按位或,其中掩码只有该位 1,其他位为零。只关闭一个位,使用按位 And 其中掩码只有那个位 0 而其他位是 1。这很费力,并且有很多测试,所以如果你想打开 2 位和关闭 3 位,这种的诡计节省了很多“如果”,但如果你只是想影响一点,那么简单的方法就可以忽略这个功能,它似乎写得不太正确。

          【讨论】:

            【解决方案7】:

            XOR 是逻辑异或。这意味着一个或另一个,但不是两者兼而有之。 这是来自维基百科的真值表。

            Input
            A | B    Output
            ---------------
            0 | 0 |  0
            0 | 1 |  1
            1 | 0 |  1
            1 | 1 |  0
            
            currentValue XOR xorMask1 = 
                00101101 xor 01000000 = 01101101
            
            01010010 AND andMask = 
                01101101 and 01000000 = 01000000
            
            01000000 XOR xorMask2 = 
                01000000 xor 01000000 = 00000000
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2018-04-27
              • 2020-02-26
              • 2013-06-21
              • 2015-05-09
              • 2013-10-12
              • 2011-02-08
              • 2022-11-18
              • 2017-06-01
              相关资源
              最近更新 更多