Koşullu XOR?


89

C # neden koşullu XORişleci içermez ?

Misal:

true  xor false = true
true  xor true  = false
false xor false = false

15
!=Yedek olarak nasıl çalışır?
Pascal Cuoq

45
C # yapar bir XOR operatörü (x ^ y) sahiptir. Bu nedenle, sorunun dayanak noktasını reddediyorum. C # 'ın bir xor operatörü olmadığına neden inandığınızı açıklayabilir misiniz? İnsanların neden C # hakkında yanlış şeylere inandıklarını öğrenmekle ilgileniyorum.
Eric Lippert

3
@Eric Lippert: Mantıksal operatörlere ( & | ^) karşı koşullu operatörlere ( && ||) atıfta bulunduğunu düşünüyorum . Ama haklısın (elbette), mantıklı bir
ÖZEL DESTEK var

14
@BoltClock: Ah, soru "neden kısa devre yapan xor operatörü yok?" İse - nasıl olabilir? "Ve" ile ilk argüman yanlışsa ikinciyi değerlendirmenize gerek yoktur. "Veya" ile, eğer ilk argüman doğruysa, ikinciyi değerlendirmenize gerek yoktur. Her zaman xor için her iki argümanı da değerlendirmeniz gerekir, bu nedenle kısa devre mümkün değildir.
Eric Lippert

4
Sorunun kendisi Microsoft'a daha uygun bir sorudur - ve bu, olumsuz oy vermek için makul bir neden - ancak bunu ^ operatörü nedeniyle reddeden kişi, o zaman ayrıntılara daha fazla dikkat etmeniz gerekir, çünkü soru koşullu vs. mantıklı, basitçe "neden bir XOR yok" değil.
The Evil Greebo

Yanıtlar:


124

C # 'da, koşullu operatörler yalnızca gerekirse ikincil işlenenlerini yürütür .

Bir XOR tanım gereği her iki değeri de test etmesi gerektiğinden , koşullu bir sürüm aptalca olacaktır.

Örnekler :

  • Mantıksal VE: &- her seferinde iki tarafı da test eder.

  • Mantıksal VEYA: |- her seferinde iki tarafı da test edin.

  • Koşullu VE: &&- 1. taraf doğruysa yalnızca 2. tarafı test eder.

  • Koşullu VEYA: ||- yalnızca 1. taraf yanlışsa 2. tarafı test edin.


37
Bir XOR işleci, "koşullu işleçler yalnızca gerekirse ikincil işlenenlerini yürütür" kuralını ihlal etmez. Sadece her zaman gerekli olacaktır.
Nathan Kovner

2
Koşullu XOR, bazı belirli modeller için hoş ve zarif bir kısayol olabilir, ancak bunu dile dahil edecek kadar haklı olup olmadığından emin değil. XOR'un yararlı olabileceği bu tür modellere bir örnek, Koşullu Olumsuzluktur: İkinci bir boole ifadesi verildiğinde, bir Boole ifadesinin olumsuzlanması veya olmaması gerektiğinde.
SalvadorGomez

1
Bir süredir buna yanıt vermedim, ancak @ KhyadHalda'nın popüler yorumuna yanıt vermek için: Neden hiç kullanılmayacağını bildiğiniz bir şeyi inşa edersiniz? Kasıtlı olarak ölü kod yazarsınız.
The Evil Greebo

2
Koşullu bir XOR nasıl faydalı olabilirdi? Koşullu bir XOR, eşit olup olmadıklarını belirlemek için her iki tarafı karşılaştırmadan asla değerlendiremez. İki bool'u karşılaştıran bir koşullu XOR kavramı bile her bool'un değerini kontrol etmeli ve eşitliği test etmelidir.
The Evil Greebo

1
Koşullu toplama operatörü kadar aptalca. Neden koşullu toplama için başka bir operatör yapılmasın, burada (a + b) yalnızca b gerekli olduğunda b'yi değerlendirir? Koşullu XOR'da olduğu gibi, bu koşullu operatörlerin kurallarını ihlal etmez, sadece ikinci argüman her zaman gerekli olacaktır. Bunun hiç bir faydası yok. Ve bu örnekte sadece bilgiçlik yapmıyorum - XOR işlemi esasen 1 bitlik bir eklemedir.
Kevin Holt

283

Soru biraz modası geçmiş ama ...

Bu operatör şu şekilde çalışmalıdır:

true xor false = true
true xor true = false
false xor true = true
false xor false = false

! = Operatörü bool türleriyle şu şekilde çalışır:

(true != false) // true
(true != true) // false
(false != true) // true
(false != false) // false

Gördüğünüz gibi ^^mevcut olmayan, mevcut olanla değiştirilebilir!=


46
Aslında soruyu doğrudan ve doğru bir şekilde ele alan tek cevap budur.
usr

40
Burada oturup !=bunun için işe yarayacağının farkında olmadığım bir şekilde kendimi elimden geçiriyorum .
AdamMc331

1
Cevap doğru ama yorumlar değil. "C # neden bir koşullu ÖZGRE'ye sahip değil?" Sorusuna hitap etmez. Açıkçası bu mantıksal bir operatör değil, ilişkisel eşitlik operatörü. Sonuç XOR ile aynı olsa da, farklı bir sınıftadır. Yalnızca iki boole değerini test ederken XOR ile karşılaştırır ve operatörün her iki tarafı da yine de değerlendirilmelidir.
The Evil Greebo

3
@TheEvilGreebo - Söyledikleriniz doğru; ! = operatörü teknik olarak koşullu bir XOR operatörü değildir. Bununla birlikte, bu yanıt etkili bir şekilde "Koşullu bir XOR operatörü mevcut değildir, çünkü! = Operatörü var" der. Zaten ben de öyle okudum.
Syndog

6
Sanırım hemen hemen her biri bu yazıya son verdi, aslında Booleans üzerine XOR yazmak istedi. gibi mantıksal var ANDve ORancak hiçbir şey XOR. ya da en azından farkına !=varmadık :) @TheEvilGreebo
M.kazem Akhgary

30

Mantıksal XOR operatörü var: ^

Belgeler: C # Operatörleri ve ^ Operatörü


2
Mantıklı, koşullu değil. Mantıksal ve = &, koşullu ve = &&. Koşullu hakkında soru soruyor.
The Evil Greebo

3
Bu ikili, mantıksal değil. CLR'de doğru olmayan bool'lerin 0 veya 1 olduğunu varsayar.
usr

1
üzgünüm, bu yanıt aslında CONDITIONAL operatörler hakkındaki soruyu yanıtlamıyor. bu biraz opperator
Nathan Tregillus

3
Kayıt için, bu cevapta bağlantısı verilen dokümantasyon ^, boolean işlenenleri ile kullanıldığında, bir boole operatörü olduğunu açıkça belirtir . "bool işlenenleri için ^ operatörü eşitsizlik operatörü ile aynı sonucu hesaplar! =". Ayrıca bit tabanlı x veya tamsayı işlenenlerini ^. C # C değildir.
15ee8f99-57ff-4f92-890c-b56153

25

Açıklık getirmek gerekirse, ^ operatörü hem integral türleri hem de bool ile çalışır.

Bkz MSDN en ^ Operatörü (C # Reference) :

İkili ^ operatörleri, integral türleri ve bool için önceden tanımlanmıştır. İntegral türleri için, ^, işlenenlerinin bitsel dışlayıcı-OR'sini hesaplar. Bool işlenenleri için ^ mantıksal dışlayıcıyı veya işlenenlerinin hesaplanır; yani, sonuç, ancak ve ancak işlenenlerinden tam olarak biri doğruysa doğrudur.

Belki de bu soru sorulduğunda belgeler 2011'den beri değişmiştir.


2
uzun zamandır c # ile programlama yapıyorum, bunu hiç bilmiyordum! teşekkürler @RichardCL!
Nathan Tregillus

Bu iyi bir bilgidir, ancak bundan ^beş yıl önce bahseden ve bundan bahseden diğer yanıta bir yorum veya düzenleme olarak daha uygun görünmektedir . Bir şeyin değiştiğinden şüpheliyim.
Chris

13

Mark L'nin sorduğu gibi , İşte doğru sürüm:

 Func<bool, bool, bool> XOR = (X,Y) => ((!X) && Y) || (X && (!Y));

İşte doğruluk tablosu:

 X | Y | Result
 ==============
 0 | 0 | 0
 1 | 0 | 1
 0 | 1 | 1
 1 | 1 | 0

Referans: Münhasır VEYA


2
Sorulan soru NEDEN C # 'nın koşullu bir XOR operatörüne sahip olmadığı idi. Bu soruya cevap vermiyor. İşlevin kendisine gelince: bu işlev koşullu ÖZELVEYA olarak çalışır - ancak soru şu ki, koşullu olmayan XOR'dan daha verimli mi? Münhasır gerçeği test etmek için, XOR bir ve tam olarak bir sonucun doğru olduğunu onaylamalıdır. Bu, her iki tarafın da değerlendirilmesi ve karşılaştırılması gerektiği anlamına gelir. Yukarıdaki işlev, bir ve koşulunun her iki tarafını en az bir değeri ters çevirirken test eder. Bunun XOR'dan farklı olup olmadığını dahili olarak biliyor muyuz?
Kötü Greebo

6

Oh evet, öyle.

bool b1 = true;
bool b2 = false;
bool XOR = b1 ^ b2;

1
Bu bir ikili operatördür, mantıksal değil. CLR'de doğru olmayan bool'lerin 0 veya 1 olduğunu varsayar. Yani bu kod aslında çalışmayabilir.
usr

6
@usr, C # 'da ^ operatörü iki Boole işlenenine uygulandığında mantıksaldır. Bu cevaplar üzerinden çok yorum yaptınız, hipotezinizi test etmek için hiç kod çalıştırdınız mı?
Marc L.

2
@MarcL. Yaptım : pastebin.com/U7vqpn6G Doğru yazdırır, ancak doğru ^ doğru yanlıştır. bool olmayan Bu CLR üzerinde mantıksal bir türü değil, her zaman, 0 ya da 1'e eşit. Keyfi içerikli 8 bitlik bir miktardır. Sorunu göstermek için doğrulanabilir bilgi okulu oluşturabilirdim.
usr

2
Örneğin C # dışındaki diğer CLR dillerini kullanırken. Tekrar ediyorum: Bunu yapan tamamen doğrulanabilir, güvenli bir derleme oluşturmak için ILASM'yi kullanabilirdim (IL düzeyinde bir boole değeri, i1tıpkı bir bayt gibi yalnızca bir değerdir ). Bu,% 100 tanımlanmış ve güvenli yönetilen bir davranıştır. CLR kabaca hazırlanmamıştır .; Bu davranışı ilk kez Microsoft Pex kullanırken gördüm.
usr

1
@EdPlunkett, kamyonunun benimle olduğunu sanmıyorum. usr, bunun dahili olarak aslında bir ikili operatör olduğunu gösterdi . Şikayet ettiğim "suistimal", onun bunu kanıtlamasının bir yoluydu ve ben hala çok sinirli. Olabilir, ancak Boolean kullanımını hiç kimsenin olmadığı toprağa o kadar kapsamlı bir şekilde koyar ki, onu CLR güvenli olarak yerleştirmek en iyi ihtimalle tehlikeli, kötü niyetli (kötü niyetli değilse) ve bir hata olarak ele alınmalıdır. Usr'nin kanıtladığı şey, C # 'ın ikimizin de düşündüğünden daha çok C'ye benzediğidir. Bunu yapan kodun geçerli kabul edilip edilmeyeceği başka bir sorudur.
Marc L.

4

Koşullu xor mevcut değildir, ancak mantıksal olanı kullanabilirsiniz, çünkü xor boole'lar için tanımlanmıştır ve tüm koşullu karşılaştırmalar boolelerle değerlendirilir.

Böylece şöyle bir şey söyleyebilirsiniz:

if ( (a == b) ^ (c == d))
{

}

Bu bir ikili operatördür, mantıksal değil. CLR'de doğru olmayan bool'lerin 0 veya 1 olduğunu varsayar. Yani bu kod aslında çalışmayabilir.
usr

@usr CLR ne demek istiyorsun? Bu benim için çalıştı, burada bir uç durumu kaçırıp kaçırmadığımdan emin değilim ...
LunaCodeGirl

3
@Spencevail, muhtemelen yanlış olmayan bir booleanın tamsayı temsiline sahip olmayabileceği durumu hakkında düşünmüyordunuz 1. Bu az bilinen bir gerçektir. İki yanlış olmayan boolean xor değerinin hala yanlış olmadığı bir duruma düşebilirsiniz! Bu belirli kodda söylendiği gibi, xor operatörü yalnızca [0,1] 'deki değerlere uygulanır, böylece yorumum (tam olarak) geçerli değildir.
usr

1
@Spencevail tam olarak başarısız olabilecek durumdur. Bir baytı aynı bitlerden oluşan bir bool'a dönüştüren güvenli bir yönetilen kod fonksiyonu CreateBool (bayt) oluşturmak mümkündür. O halde, CreateBool (1) ^ CreateBool (2) doğrudur, ancak CreateBool (1) doğrudur ve CreateBool (2) de doğrudur! &ayrıca savunmasızdır.
usr

1
Aslında, bir RyuJIT hatası bildirdim çünkü bu olasılığı dikkate almadılar ve yanlış derlemeymiş &&gibi derlediler &.
usr

3

Bir olsa da mantıksal xor operatörü ^, hiçbir orada koşullu xor operatörü. Aşağıdakileri kullanarak A ve B değerlerinden oluşan bir koşullu xor elde edebilirsiniz:

A ? (!B) : B

Parenler gerekli değildir, ancak açıklık için onları ekledim.

Evil Greebo tarafından sivri dışarı olarak, bu değerlendirir her iki ifade, ama xor kısa gibi devre edilemez ve ve veya .


Mantıkçı ^ ile koşullu ^ arasındaki fark nedir? oO
Armen Tsirunyan

@Armen Tsirunyan Mantıksal operatörler, koşullu operatörler boole değerleri üzerinde çalışırken ve bir boole sonucu döndürürken mantıklı olan türlerde bitsel işlemler gerçekleştirir. Boole değerleri göz önüne alındığında: 0101 ^ 0011değere sahiptir 0110.
jimreed

3
hayır, tamamen yanılıyorsun. C # 'da her iki tür XOR vardır (bunlar sırasıyla bitsel ve mantıksal olarak adlandırılır). Her ikisi de ^ sembolünü kullanır.
Armen Tsirunyan

1

kullanabilirsiniz:

a = b ^ c;

tıpkı c / c ++ 'da olduğu gibi


0

Koşullu (kısa devre) XOR diye bir şey yoktur. Koşullu operatörler, yalnızca ilk argümana bakarak nihai sonucu kesin olarak söylemenin bir yolu olduğunda anlamlıdır. XOR (ve toplama) her zaman iki argüman gerektirir, bu nedenle ilk argümandan sonra kısa devre yapmanın bir yolu yoktur.

A = doğru olduğunu biliyorsanız, (A XOR B) =! B.

A = yanlış olduğunu biliyorsanız, (A XOR B) = B.

Her iki durumda da, eğer A'yı biliyor ama B'yi bilmiyorsanız, o zaman bilmek için yeterli bilginiz yoktur (A ÖZEL B). Cevabı hesaplamak için her zaman hem A hem de B'nin değerlerini öğrenmelisiniz. XOR'u her iki değer olmadan çözebileceğiniz hiçbir kullanım durumu yoktur.

XOR'un tanım gereği dört durumu olduğunu unutmayın:

false xor true  = true
true  xor false = true
true  xor true  = false
false xor false = false

Yine, umarım yukarıdakilerden, ilk değeri bilmenin, ikinci değeri de bilmeden yanıtı almak için asla yeterli olmadığı açıktır. Ancak sorunuzda ilk vakayı atladınız. Bunun yerine istersen

false op true  = false (or DontCare)
true  op false = true
true  op true  = false
false op false = false

o zaman bunu kısa devre yapan bir koşullu işlemle elde edebilirsiniz:

A && !B

Ama bu bir XOR değil.


Bu yanıtta yukarıdaki yanıtlardan en az birinde olmayan hiçbir şey görmüyorum. Uygun xor istediğini varsayan bir cevabı kabul ettiği için, OP'nin aradığı kısa devre edilebilir xor olmadığına dair herhangi bir gösterge görmüyorum.
15ee8f99-57ff-4f92-890c-b56153

Benimki, ikinci argümanı değerlendirmeden OP'nin talep edilen doğruluk tablosunu oluşturabilen şimdiye kadar önerilen tek cevaptır.
Kevin Holt

Ayrıca OP, neden koşullu XOR olmadığını sordu ve yukarıdaki yanıtlar, XOR'un iki argüman gerektirdiği için doğru olduğunu söylese de, IMO yukarıdaki cevaplar, XOR'un gerçekte iki argümana neden ihtiyaç duyduğunu yeterince açıklamıyor gibi görünüyor. Açıkçası aksini hissediyorsunuz, ama bana göre bu sayfadaki çeşitli yorumlardan, XOR'un temel iki argümanının henüz tam bir acemi kişiye tam olarak açıklanmadığı anlaşılıyordu.
Kevin Holt

1
Beni ikna ettin.
15ee8f99-57ff-4f92-890c-b56153

@Kevin Holt - Mantıksal XOR, koşullardan birinin doğru olmasına, ancak ikisine birden ihtiyacınız varsa anlamlıdır. Her iki koşulu da değerlendirmeniz gerektiği önemli değil. Kısa devre meselesi, yalnızca performans kritik koduyla uğraşırken endişelenmeniz gereken düşük seviyeli bir ayrıntıdır (kontrol akışı yavaştır). Bundan mantıksal bir operatör oluştururken "özel veya" nin ne anlama geldiği ile daha çok ilgilenirim. Yani, bitsel sürüm gibi çalışmasını sağlayın (diğer operatörler gibi) veya onu özel veya özel yapın (istediğiniz kadar çok koşul, ancak yalnızca biri doğru olabilir).
Thorham

-3

Bu soru etkili bir şekilde yanıtlandı, ancak farklı bir durumla karşılaştım. Koşullu bir XOR'a gerek olmadığı doğrudur. ^ Operatörünün kullanılabileceği de doğrudur. Ancak, işlenenlerin yalnızca "doğru || yanlış" durumunu test etmeniz gerekiyorsa, ^ soruna yol açabilir. Örneğin:

void Turn(int left, int right)
{
    if (left ^ right)
    {
        //success... turn the car left or right...
    }
    else
    {
        //error... no turn or both left AND right are set...
    }
}

Bu örnekte, sol 10 (0xa) ve sağ 5 (0x5) olarak ayarlanmışsa, "başarılı" dal girilir. Bu (aptalca olsa da basit) örnek için, aynı anda sola VE sağa dönmemeniz gerektiğinden, bu bir hataya neden olur. Sorguyu soran kişiden öğrendiğim şey, aslında bir koşullu istediği değil, xor'a aktarılan değerler üzerinde doğru / yanlışı gerçekleştirmenin basit bir yoluydu.

Bir makro hile yapabilir:

#define my_xor(a, b) ( ((a)?1:0) ^ ((b)?1:0) )

İşaretin dışına çıkarsam beni tokatlamaktan çekinmeyin: o)

Bunu gönderdikten sonra (kötü Yapdog!) Jimreed'in cevabını aşağıda okudum ve onunki aslında daha basit. İşe yarardı ve cevabının neden reddedildiğine dair hiçbir fikrim yok ...


3
Bu bir C # sorusudur, C / C ++ değil. ifBoolean ifadesi gerektirir, int ile bile derlenmez.
Marc L.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.