[英]Why is there no logical XOR?
為什么JavaScript沒有邏輯XOR
或?
JavaScript 將其祖先追溯到 C,而 C 沒有邏輯 XOR 運算符。 主要是沒用。 按位異或非常有用,但在我多年的編程生涯中,我從來不需要邏輯異或。
如果你有兩個布爾變量,你可以模擬異或:
if (a != b)
使用兩個任意變量,您可以使用!
將它們強制為布爾值,然后使用相同的技巧:
if (!a != !b)
雖然這很晦澀,但肯定值得評論。 實際上,此時您甚至可以使用按位 XOR 運算符,盡管這對我來說太聰明了:
if (!a ^ !b)
Javascript 有一個按位異或運算符:^
var nb = 5^9 // = 12
您可以將它與布爾值一起使用,它會將結果作為 0 或 1(您可以將其轉換回布爾值,例如result = !!(op1 ^ op2)
)。 但正如約翰所說,它相當於result = (op1 != op2)
,更清楚。
Javascript 中沒有真正的邏輯布爾運算符(盡管!
非常接近)。 邏輯運算符只會將true
或false
作為操作數,並且只會返回true
或false
。
在 Javascript &&
和||
中采用各種操作數並返回各種有趣的結果(無論您輸入什么)。
此外,邏輯運算符應始終考慮兩個操作數的值。
在 Javascript &&
和||
中采取懶惰的捷徑,在某些情況下不評估第二個操作數,從而忽略其副作用。 使用邏輯異或無法重新創建此行為。
a() && b()
評估a()
並返回結果(如果它是假的)。 否則它計算b()
並返回結果。 因此,如果兩個結果都為真,則返回的結果為真,否則為假。
a() || b()
a() || b()
評估a()
並返回結果(如果為真)。 否則它計算b()
並返回結果。 因此,如果兩個結果均為假,則返回的結果為假,否則為真。
所以一般的想法是先評估左操作數。 正確的操作數只有在必要時才會被評估。 最后一個值就是結果。 這個結果可以是任何東西。 對象、數字、字符串……隨便什么!
這使得編寫類似的東西成為可能
image = image || new Image(); // default to a new Image
要么
src = image && image.src; // only read out src if we have an image
但是這個結果的真值也可以用來決定一個“真正的”邏輯運算符是否會返回 true 或 false。
這使得編寫類似的東西成為可能
if (typeof image.hasAttribute === 'function' && image.hasAttribute('src')) {
要么
if (image.hasAttribute('alt') || image.hasAttribute('title')) {
但是“邏輯”異或運算符 ( ^^
) 總是必須評估兩個操作數。 這使得它不同於僅在必要時才評估第二個操作數的其他“邏輯”運算符。 我認為這就是為什么在 Javascript 中沒有“邏輯”異或,以避免混淆。
那么如果兩個操作數都是假的,會發生什么? 兩者都可以退貨。 但是只能退一個。 哪一個? 第一個? 還是第二個? 我的直覺告訴我返回第一個但通常是“邏輯”運算符從左到右評估並返回最后評估的值。 或者可能是一個包含這兩個值的數組?
如果一個操作數為真而另一個操作數為假,則異或應返回真值。 或者可能是一個包含真實數組的數組,以使其與前一種情況兼容?
最后,如果兩個操作數都為真,會發生什么? 你會期待一些虛假的東西。 但是沒有錯誤的結果。 所以這個操作不應該返回任何東西。 所以也許undefined
或.. 一個空數組? 但是空數組仍然是真實的。
采用數組方法,您最終會遇到類似if ((a ^^ b).length !== 1) {
的條件。 非常混亂。
兩個布爾值的異或只是它們是否不同,因此:
Boolean(a) !== Boolean(b)
將值轉換為布爾形式,然后進行按位異或:
Boolean(a) ^ Boolean(b) // === 0 | 1
請注意,此表達式的結果是一個數字而不是布爾值。
按位異或也適用於非布爾值,但請記住這是一個按位運算符,而不是邏輯運算符。 使用非布爾值可能不會像您最初預期的那樣:
(5 ^ 3) === 6 // true
隱蔽為布爾值,然后像執行 xor -
!!a ^ !!b
有...有點:
if( foo ? !bar : bar ) {
...
}
或者更容易閱讀:
if( ( foo && !bar ) || ( !foo && bar ) ) {
...
}
為什么? 不知道。
因為 javascript 開發人員認為這是不必要的,因為它可以由其他已經實現的邏輯運算符表示。
您也可以只使用 nand 和僅此而已,您可以從中給所有其他可能的邏輯操作留下深刻印象。
我個人認為它有歷史原因驅動基於 c 的語法語言,據我所知 xor 不存在或至少不常見。
是的,只需執行以下操作。 假設您正在處理布爾值 A 和 B,那么可以使用以下代碼在 JavaScript 中計算 A XOR B 值
var xor1 = !(a === b);
上一行也等同於以下
var xor2 = (!a !== !b);
就個人而言,我更喜歡 xor1,因為我需要輸入的字符更少。 我相信 xor1 也更快。 它只是執行兩個計算。 xor2 正在執行三個計算。
視覺解釋...閱讀下表(其中 0 代表錯誤,1 代表正確)並比較第 3 列和第 5 列。
:(A === B):
| A | B | A XOR B | A === B | !(A === B) |
------------------------------------------
| 0 | 0 | 0 | 1 | 0 |
| 0 | 1 | 1 | 0 | 1 |
| 1 | 0 | 1 | 0 | 1 |
| 1 | 1 | 0 | 1 | 0 |
------------------------------------------
享受。
如何將結果int轉換為帶有雙重否定的bool ? 不是很漂亮,但真的很緊湊。
var state1 = false, state2 = true; var A = state1 ^ state2; // will become 1 var B =;.(state1 ^ state2); // will become true console.log(A); console.log(B);
為了后代的利益,並且因為我發現這是一個很好的練習,您可以很容易地利用 XOR 運算符的真實性來強制執行。 就像選擇的答案一樣,它可能有點太聰明了。
const xor = (a, b) => !!(!!a ^ !!b)
console.log(undefined ^ {}) // Returns 0, bitwise can't be done here.
console.log(xor(undefined, {})) // Returns true, because {} is truthy and undefined is falsy
console.log(0 ^ 1) // Works naturally, returns 1
console.log(xor(0, 1)) // Also works, returns true
console.log(true ^ false) // Again, returns true
console.log(xor(true, false)) // And again, returns true...
為了好玩,這應該在 TypeScript 中工作,通過強制顯式 any:
const xor = (a: any, b: any) => !!((!!a as any) ^ (!!b as any))
布爾值的一種襯墊:
if (x ? !y : y) { do something cool }
在上面的異或函數中,它會產生類似的結果,因為邏輯異或不完全是邏輯異或,這意味着它將產生“相等值為假”和“不同值為真”並考慮數據類型匹配。
這個 xor 函數將作為實際的 xor 或邏輯運算符工作,這意味着它會根據傳遞的值是truthy還是falsy來產生 true 或 false 。 根據您的需要使用
function xor(x,y){return true==(!!x!==!!y);}
function xnor(x,y){return !xor(x,y);}
沒有邏輯 XOR (^^) 的原因是因為不像 && 和 || 它不會提供任何惰性邏輯優勢。 也就是說,必須評估左右兩個表達式的狀態。
在 Typescript 中(+ 變為數值):
value : number = (+false ^ +true)
所以:
value : boolean = (+false ^ +true) == 1
cond1 xor cond2
等同於cond1 + cond 2 == 1
:
這是證明:
let ops = [[false, false],[false, true], [true, false], [true, true]]; function xor(cond1, cond2){ return cond1 + cond2 == 1; } for(op of ops){ console.log(`${op[0]} xor ${op[1]} is ${xor(op[0], op[1])}`) }
這是一個替代解決方案,適用於 2+ 個變量並提供計數作為獎勵。
這是一個更通用的解決方案,可以為任何真值/假值模擬邏輯異或,就像您在標准 IF 語句中使用運算符一樣:
const v1 = true; const v2 = -1; // truthy (warning, as always) const v3 = ""; // falsy const v4 = 783; // truthy const v5 = false; if( (.;v1 +.;v2 + !!v3 + !!v4 + !!v5 ) === 1 ) document.write( `[ ${v1} XOR ${v2} XOR "${v3}" XOR ${v4} XOR ${v5} ] is TRUE!` ); else document.write( `[ ${v1} XOR ${v2} XOR "${v3}" XOR ${v4} XOR ${v5} ] is FALSE!` );
我喜歡這個的原因是因為它還回答了“這些變量中有多少是真實的?”,所以我通常會預先存儲那個結果。
對於那些想要嚴格的 boolean-TRUE 異或檢查行為的人,只需執行以下操作:
if( ( ( v1===true ) + ( v2===true ) + ( v3===true ) + ( v4===true ) + ( v5===true ) ) === 1 )
// etc.
如果您不關心計數,或者您關心最佳性能:那么只需對強制為布爾值的值使用按位異或,以獲得真/假解決方案:
if( !!v1 ^ !!v2 ^ !!v3 ^ !!v4 ^ !!v5 )
// etc.
嘿,我找到了這個解決方案,可以在 JavaScript 和 TypeScript 上進行異或運算。
if( +!!a ^ +!!b )
{
//This happens only when a is true and b is false or a is false and b is true.
}
else
{
//This happens only when a is true and b is true or a is false and b is false
}
這里提出的大多數方法都很難閱讀和理解。 與其編寫一些神秘而神奇的比較或試圖評論它們,不如定義一個不言自明的可重用 function :
function either(a: boolean, b: boolean): boolean {
return (a !== b);
}
或者更通用的:
function either(a: any, b: any): boolean {
return Boolean(a) !== Boolean(b);
}
然后你可以像這樣使用它:
assert(either(one, another), 'Either one or another, not both');
試試這個簡短易懂的
function xor(x,y){return true==(x!==y);}
function xnor(x,y){return !xor(x,y);}
這適用於任何數據類型
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.