简体   繁体   English

三个值的异或

[英]XOR of three values

What is the simplest way to do a three-way exclusive OR?做三路异或的最简单方法是什么?

In other words, I have three values, and I want a statement that evaluates to true IFF only one of the three values is true.换句话说,我有三个值,并且我想要一个评估为真 IFF 的语句,只有三个值中的一个为真。

So far, this is what I've come up with:到目前为止,这就是我想出的:

((a ^ b) && (a ^ c) && !(b && c)) || ((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b)) ((c ^ a) && (c ^ b) && !(a && b))

Is there something simpler to do the same thing?有没有更简单的方法来做同样的事情?


Here's the proof that the above accomplishes the task:这是上述完成任务的证明:

a = true; b = true; c = true
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false

a = true; b = true; c = false
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false

a = true; b = false; c = true
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false

a = true; b = false; c = false
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> true

a = false; b = true; c = true
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false

a = false; b = true; c = false
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> true

a = false; b = false; c = true
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> true

a = false; b = false; c = false
((a ^ b) && (a ^ c) && !(b && c)) || ((b ^ a) && (b ^ c) && !(a && c)) || ((c ^ a) && (c ^ b) && !(a && b))
=> false

For exactly three terms, you can use this expression:对于三个术语,您可以使用以下表达式:

(a ^ b ^ c) && !(a && b && c)

The first part is true iff one or three of the terms are true .如果其中一个或三个术语为true true The second part of the expression ensures that not all three are true .表达式的第二部分确保并非所有三个都为true

Note that the above expression does NOT generalize to more terms.请注意,上述表达式并未推广到更多术语。 A more general solution is to actually count how many terms are true , so something like this:一个更通用的解决方案是实际计算有多少项是true ,所以像这样:

int trueCount =
   (a ? 1 : 0) +
   (b ? 1 : 0) +
   (c ? 1 : 0) +
   ... // more terms as necessary 

return (trueCount == 1); // or some range check expression etc
bool result = (a?1:0)+(b?1:0)+(c?1:0) == 1;

a^b^c is only 1 if an uneven number of variables is 1 (two '1' would cancel each other out). a^b^c只有在奇数个变量为 1 时才为 1(两个 '1' 会相互抵消)。 So you just need to check for the case "all three are 1":所以你只需要检查“所有三个都是1”的情况:

result = (a^b^c) && !(a&&b&&c)

Another possibility:另一种可能:

a ? !b && !c : b ^ c

which happens to be 9 characters shorter than the accepted answer :)这恰好比接受的答案短 9 个字符:)

Better yet on Python:在 Python 上更好:

result = (1 if a else 0)+(1 if b else 0)+(1 if c else 0) == 1

This can be used also on if statements!这也可以用于 if 语句!

It saved my day for CLI mutually exclusive arguments through Click (everyone hates click)它通过 Click 为 CLI 互斥参数节省了我的时间(每个人都讨厌点击)

您也可以尝试(在 C 中):

!!a + !!b + !!c == 1

f= lambda{ |a| [false, false, true].permutation.to_a.uniq.include? a }
p f.call([false, true, false])
p f.call([false, true, true])

$ true $ 真

$ false $假

Because I can.因为我可以。

Here's a general implementation that fails quickly when more than one bool is found to be true .这是一个通用实现,当发现多个booltrue时会迅速失败。

Usage :用法

XOR(a, b, c);

Code :代码

public static bool XOR(params bool[] bools)
{
    return bools.Where(b => b).AssertCount(1);
}

public static bool AssertCount<T>(this IEnumerable<T> source, int countToAssert)
{
    int count = 0;
    foreach (var t in source)
    {
        if (++count > countToAssert) return false;
    }

    return count == countToAssert;
}

In C:在 C 中:

#include <stdbool.h>

bool array_xor(size_t array_size, bool[] array) {
    int count = 0;

    for (int i = 0; i < array_size && count < 2; i++) {
        if (array[i]) {
            count++;
        }
    }

    return count == 1;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM