簡體   English   中英

三個值的異或

[英]XOR of three values

做三路異或的最簡單方法是什么?

換句話說,我有三個值,並且我想要一個評估為真 IFF 的語句,只有三個值中的一個為真。

到目前為止,這就是我想出的:

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

有沒有更簡單的方法來做同樣的事情?


這是上述完成任務的證明:

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

對於三個術語,您可以使用以下表達式:

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

如果其中一個或三個術語為true true 表達式的第二部分確保並非所有三個都為true

請注意,上述表達式並未推廣到更多術語。 一個更通用的解決方案是實際計算有多少項是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只有在奇數個變量為 1 時才為 1(兩個 '1' 會相互抵消)。 所以你只需要檢查“所有三個都是1”的情況:

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

另一種可能:

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

這恰好比接受的答案短 9 個字符:)

在 Python 上更好:

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

這也可以用於 if 語句!

它通過 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])

$ 真

$假

因為我可以。

這是一個通用實現,當發現多個booltrue時會迅速失敗。

用法

XOR(a, b, c);

代碼

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;
}

在 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