XOR bersyarat?

89

Kenapa C # tidak memiliki XORoperator bersyarat ?

Contoh:

true  xor false = true
true  xor true  = false
false xor false = false
Gilad Naaman
sumber
15
Bagaimana cara !=bekerja sebagai penggantinya?
Pascal Cuoq
45
C # memang memiliki operator xor (x ^ y). Oleh karena itu, saya menyangkal premis pertanyaan tersebut. Bisakah Anda menjelaskan mengapa Anda percaya bahwa C # tidak memiliki operator xor? Saya tertarik untuk mempelajari mengapa orang mempercayai hal-hal palsu tentang C #.
Eric Lippert
3
@ Eric Lippert: Saya pikir dia mengacu pada operator logis ( & | ^) vs operator bersyarat ( && ||). Tapi Anda benar (tentu saja), ada XOR yang logis ...
BoltClock
14
@BoltClock: Oh, jika pertanyaannya adalah "mengapa tidak ada operator xor yang mengalami korsleting?" - bagaimana bisa ada? Dengan "dan" jika argumen pertama salah, Anda tidak perlu mengevaluasi argumen kedua. Dengan "atau", jika argumen pertama benar maka Anda tidak perlu mengevaluasi argumen kedua. Anda selalu perlu mengevaluasi kedua argumen untuk xor, jadi tidak mungkin terjadi korsleting.
Eric Lippert
4
Pertanyaan itu sendiri lebih cocok untuk Microsoft - dan itulah alasan yang layak untuk downvote - tetapi jika siapa pun yang downvote melakukannya karena operator ^, maka Anda perlu membaca dengan lebih memperhatikan detail, karena pertanyaannya bersyarat vs. logis, bukan hanya "mengapa tidak ada XOR".
The Evil Greebo

Jawaban:

124

Di C #, operator bersyarat hanya menjalankan operan sekundernya jika perlu .

Karena XOR harus secara definisi menguji kedua nilai, versi bersyarat akan menjadi konyol.

Contoh :

  • DAN Logis: &- menguji kedua sisi setiap waktu.

  • Logis ATAU: |- uji kedua sisi setiap waktu.

  • AND bersyarat: &&- hanya menguji sisi ke-2 jika sisi ke-1 benar.

  • Bersyarat OR: ||- hanya uji sisi ke-2 jika sisi ke-1 salah.

The Evil Greebo
sumber
37
Operator XOR tidak akan melanggar konvensi "operator bersyarat hanya mengeksekusi operan sekundernya jika perlu". Itu akan selalu diperlukan.
Nathan Kovner
2
XOR bersyarat bisa menjadi jalan pintas yang bagus dan elegan untuk beberapa pola tertentu, meskipun tidak yakin apakah cukup dibenarkan untuk memasukkannya ke dalam bahasa. Contoh pola di mana XOR mungkin terbukti berguna, adalah Negasi Bersyarat: Ketika ekspresi Boolean harus dinegasikan atau tidak, diberikan ekspresi Boolean kedua.
SalvadorGomez
1
Belum menanggapi ini dalam beberapa waktu tetapi untuk menanggapi komentar populer dari @KadHalda: Mengapa Anda pernah membangun sesuatu yang Anda tahu tidak akan pernah digunakan? Anda akan dengan sengaja menulis kode mati.
The Evil Greebo
2
Bagaimana, pernah, apakah XOR bersyarat akan berguna? XOR bersyarat tidak akan pernah dapat mengevaluasi tanpa membandingkan kedua sisi untuk menentukan bahwa keduanya sama atau tidak sama. Bahkan gagasan tentang XOR bersyarat yang membandingkan dua bool masih harus memeriksa nilai setiap bool dan menguji kesetaraan.
The Evil Greebo
1
Ini konyol seperti operator penjumlahan bersyarat. Mengapa tidak membuat operator lain untuk penjumlahan bersyarat, di mana (a + b) hanya mengevaluasi b jika b diperlukan? Sama seperti dengan XOR bersyarat, ini tidak akan melanggar konvensi operator bersyarat, hanya saja argumen kedua akan selalu diperlukan. Tidak ada kasus penggunaan untuk ini. Dan saya tidak hanya bertele-tele dengan contoh ini - operasi XOR pada dasarnya adalah tambahan 1-bit.
Kevin Holt
283

Pertanyaan agak ketinggalan jaman tapi ...

Begitulah cara kerja operator ini:

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

Beginilah caranya! = Operator bekerja dengan tipe bool:

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

Jadi seperti yang Anda lihat yang belum ada ^^bisa diganti dengan yang sudah ada!=

piotrpo.dll
sumber
46
Ini sebenarnya satu-satunya jawaban yang menjawab pertanyaan secara langsung dan benar.
usr
40
Saya duduk di sini sambil memalingkan muka, yang tidak saya sadari !=akan berhasil untuk ini.
AdamMc331
1
Jawabannya benar tapi komentarnya tidak. Ini tidak menjawab pertanyaan, yaitu "mengapa C # tidak memiliki XOR bersyarat?". Sebenarnya ini bukan operator logika, ini adalah operator persamaan relasional. Hasilnya sama dengan XOR, namun berada di kelas yang berbeda. Ini hanya membandingkan dengan XOR saat menguji dua nilai boolean, dan kedua sisi operator masih harus dievaluasi.
The Evil Greebo
3
@TheEvilGreebo - Apa yang Anda katakan itu benar; operator! = secara teknis bukanlah operator XOR bersyarat. Namun, jawaban ini secara efektif mengatakan, "Operator XOR bersyarat tidak ada karena operator! = Ada." Begitulah cara saya membacanya.
Syndog
6
Saya pikir hampir setiap orang yang berakhir dengan posting ini sebenarnya ingin menulis XOR di Boolean. seperti ada yang logis ANDdan ORtetapi tidak ada sebagai XOR. atau setidaknya kami tidak menyadarinya !=:) @TheEvilGreebo
M.kazem Akhgary
30

Ada operator XOR logis: ^

Dokumentasi: C # Operator dan ^ Operator

iceaway
sumber
2
Logis, bukan bersyarat. Logis dan = &, bersyarat dan = &&. Dia bertanya tentang Conditional.
The Evil Greebo
3
Ini biner, tidak logis. Ini mengasumsikan bahwa bools adalah 0 atau 1 yang tidak benar di CLR.
usr
1
maaf, jawaban ini sebenarnya tidak menjawab pertanyaan tentang CONDITIONAL operator. ini sedikit opperator
Nathan Tregillus
3
Sebagai catatan, dokumentasi yang ditautkan dalam jawaban ini secara eksplisit menyatakan bahwa ^, jika digunakan dengan operand boolean, adalah operator boolean. "untuk operan bool, operator ^ menghitung hasil yang sama dengan operator pertidaksamaan! =". Anda juga bisa menggunakan bitwise-xor integer operand ^. C # bukan C.
15ee8f99-57ff-4f92-890c-b56153
25

Hanya sebagai klarifikasi, operator ^ bekerja dengan tipe integral dan bool.

Lihat ^ Operator MSDN (C # Reference) :

Operator biner ^ telah ditentukan sebelumnya untuk tipe integral dan bool. Untuk tipe integral, ^ menghitung bitwise eksklusif-OR dari operannya. Untuk operan bool, ^ menghitung eksklusif logis-atau operannya; Artinya, hasilnya benar jika dan hanya jika salah satu operannya benar.

Mungkin dokumentasinya sudah berubah sejak 2011 ketika pertanyaan ini diajukan.

RichardCL
sumber
2
sudah lama memprogram di c #, tidak pernah tahu ini! terima kasih @RichardCL!
Nathan Tregillus
Ini adalah informasi yang bagus tetapi tampaknya lebih sesuai sebagai komentar atau edit jawaban lain yang menyebutkan ^dan mendahului satu per lima tahun ini. Saya ragu ada yang berubah.
Chris
13

Seperti yang ditanyakan oleh Mark L , Ini versi yang benar:

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

Berikut tabel kebenarannya:

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

Referensi: Exclusive OR

Rekan Sederhana
sumber
2
Pertanyaan yang diajukan adalah MENGAPA C # tidak memiliki operator XOR bersyarat. Ini tidak menjawab pertanyaan itu. Mengenai fungsi itu sendiri: fungsi ini beroperasi sebagai XOR bersyarat - namun pertanyaannya adalah, apakah ini lebih efisien daripada XOR non-kondisional? Untuk menguji kebenaran eksklusif, XOR harus memastikan bahwa satu dan tepat satu hasil adalah benar. Artinya, kedua sisi harus dievaluasi dan dibandingkan. Fungsi di atas menguji kedua sisi dari sebuah dan kondisi sambil membalikkan satu nilai, minimal. Apakah kita tahu secara internal jika ini berbeda dari XOR?
The Evil Greebo
6

Oh ya, benar.

bool b1 = true;
bool b2 = false;
bool XOR = b1 ^ b2;
Armen Tsirunyan
sumber
1
Ini adalah operator biner, bukan yang logis. Ini mengasumsikan bahwa bools adalah 0 atau 1 yang tidak benar di CLR. Jadi kode ini sebenarnya bisa gagal berfungsi.
usr
6
@usr, Dalam C #, operator ^ logis bila diterapkan ke dua operan Boolean. Anda banyak berkomentar melalui jawaban ini, apakah Anda pernah menjalankan kode apa pun untuk menguji hipotesis Anda?
Marc L.
2
@Tokopedia Saya melakukannya: pastebin.com/U7vqpn6G Mencetak true, meskipun true ^ true seharusnya salah. bool tidak selalu sama dengan 0 atau 1. Ini bukan tipe logis di CLR. Ini adalah kuantitas 8 bit dengan konten sewenang-wenang. Saya bisa saja menghasilkan IL yang dapat diverifikasi untuk mendemonstrasikan masalah tersebut juga.
usr
2
Saat menggunakan bahasa CLR selain C # misalnya. Saya ulangi: Saya dapat menggunakan ILASM untuk membuat rakitan yang sepenuhnya dapat diverifikasi dan aman yang melakukan ini (pada tingkat IL nilai boolean hanyalah an i1, sama seperti byte). Ini adalah perilaku yang 100% ditentukan dan dikelola dengan aman. CLR tidak dibuat kasar .; Pertama kali saya melihat perilaku ini adalah saat menggunakan Microsoft Pex.
usr
1
@EdPlunkett, saya rasa truk Anda tidak ada bersama saya. usr menunjukkan bahwa secara internal itu sebenarnya adalah operator biner . "Pelecehan" yang saya keluhkan adalah cara dia membuktikannya, yang masih saya pertahankan terlalu tegang. Ini mungkin saja terjadi, tetapi menempatkan penggunaan Boolean secara menyeluruh ke tanah tak bertuan sehingga untuk menyebarkannya sebagai CLR-safe akan sangat berbahaya, paling buruk menyinggung (jika tidak berbahaya), dan harus diperlakukan sebagai bug. Apa usr membuktikan bahwa secara internal C # lebih mirip C daripada yang kita pikirkan. Apakah kode yang melakukan ini harus dianggap valid adalah pertanyaan lain.
Marc L.
4

Xor bersyarat tidak ada, tetapi Anda dapat menggunakan logika yang logis karena xor didefinisikan untuk boolean, dan semua perbandingan bersyarat dievaluasi menjadi boolean.

Jadi Anda bisa mengatakan sesuatu seperti:

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

}
Klark
sumber
Ini adalah operator biner, bukan yang logis. Ini mengasumsikan bahwa bools adalah 0 atau 1 yang tidak benar di CLR. Jadi kode ini sebenarnya bisa gagal berfungsi.
usr
@ usr apa maksudmu CLR? Ini berhasil untuk saya, tidak yakin apakah saya melewatkan kasus tepi di sini ...
LunaCodeGirl
3
@Spencevail Anda mungkin tidak memikirkan kasus di mana boolean non-false mungkin tidak memiliki representasi integer 1. Ini adalah fakta yang sedikit diketahui. Anda bisa berakhir dalam situasi di mana xor dari dua boolean bukan salah masih tetap tidak salah! Yang mengatakan dalam kode khusus ini operator xor hanya pernah diterapkan ke nilai dalam [0,1] sehingga komentar saya tidak berlaku (sepenuhnya).
usr
1
@Spencevail itulah yang bisa gagal. Dimungkinkan untuk membuat fungsi kode yang dikelola dengan aman CreateBool (byte) yang mengubah byte menjadi kumpulan bit yang sama. Kemudian, CreateBool (1) ^ CreateBool (2) benar, tetapi CreateBool (1) benar dan CreateBool (2) benar juga! &juga rentan.
usr
1
Sebenarnya, saya baru saja melaporkan bug RyuJIT karena mereka tidak mempertimbangkan kemungkinan ini dan mengkompilasi &&seolah-olah itu &adalah kesalahan kompilasi.
usr
3

Meskipun ada operator xor logis^ , tidak ada operator xor bersyarat . Anda dapat mencapai xor bersyarat dari dua nilai A dan B menggunakan berikut ini:

A ? (!B) : B

Paren tidak perlu, tetapi saya menambahkannya untuk kejelasan.

Seperti keluar menunjuk oleh The Evil Greebo, mengevaluasi ini baik ekspresi, tapi xor tidak dapat hubung singkat seperti dan dan atau .

jimreed
sumber
Apa perbedaan antara logican ^ dan conditional ^? oO
Armen Tsirunyan
@Armen Tsirunyan Operator logika melakukan operasi bitwise dalam tipe yang masuk akal saat operator bersyarat beroperasi pada nilai boolean dan mengembalikan hasil boolean. Mempertimbangkan nilai boolean: 0101 ^ 0011memiliki nilai 0110.
jimreed
3
tidak, Anda sepenuhnya salah. ada kedua jenis XOR (masing-masing disebut bitwise dan logis) di C #. Keduanya menggunakan simbol ^.
Armen Tsirunyan
1

Kamu dapat memakai:

a = b ^ c;

seperti di c / c ++

gulyan
sumber
0

Tidak ada yang namanya XOR bersyarat (korsleting). Operator bersyarat hanya berarti jika ada cara untuk secara pasti memberi tahu hasil akhir dari hanya melihat argumen pertama. XOR (dan penjumlahan) selalu membutuhkan dua argumen, jadi tidak ada cara untuk melakukan hubungan pendek setelah argumen pertama.

Jika Anda mengetahui A = true, maka (A XOR B) =! B.

Jika Anda mengetahui A = salah, maka (A XOR B) = B.

Dalam kedua kasus tersebut, jika Anda mengetahui A tetapi tidak B, maka Anda tidak cukup tahu untuk mengetahui (A XOR B). Anda harus selalu mempelajari nilai A dan B untuk menghitung jawabannya. Secara harfiah tidak ada kasus penggunaan di mana Anda dapat menyelesaikan XOR tanpa kedua nilai tersebut.

Perlu diingat, XOR menurut definisi memiliki empat kasus:

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

Sekali lagi semoga dari penjelasan di atas sudah jelas bahwa mengetahui nilai pertama tidak pernah cukup untuk mendapatkan jawaban tanpa juga mengetahui nilai kedua. Namun, dalam pertanyaan Anda, Anda mengabaikan kasus pertama. Jika Anda malah menginginkan

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

maka Anda memang bisa mendapatkannya dengan operasi bersyarat hubung singkat:

A && !B

Tapi itu bukan XOR.

Kevin Holt
sumber
Saya tidak melihat apa pun dalam jawaban ini yang tidak ada di setidaknya satu jawaban di atas. Saya tidak melihat indikasi bahwa un-xor short-circuitable Anda adalah yang dicari OP, karena dia menerima jawaban yang mengasumsikan dia menginginkan xor yang tepat.
15ee8f99-57ff-4f92-890c-b56153
Saya secara harfiah adalah satu-satunya jawaban yang disarankan sejauh ini yang dapat menghasilkan tabel kebenaran yang diminta OP tanpa mengevaluasi argumen kedua.
Kevin Holt
Juga OP bertanya mengapa tidak ada XOR bersyarat, dan sementara jawaban di atas mengatakan dengan benar bahwa itu karena XOR membutuhkan dua argumen, IMO jawaban di atas sepertinya tidak cukup menjelaskan MENGAPA XOR sebenarnya membutuhkan dua argumen. Jelas Anda merasa sebaliknya, tetapi bagi saya terlihat dari berbagai komentar di halaman ini bahwa dua argumen dasar XOR belum sepenuhnya dijelaskan kepada seorang pemula yang lengkap.
Kevin Holt
1
Anda membujuk saya ke dalamnya.
15ee8f99-57ff-4f92-890c-b56153
@Kevin Holt - Logical XOR berarti jika Anda membutuhkan salah satu kondisi agar benar, tetapi tidak keduanya. Bahwa Anda harus mengevaluasi kedua kondisi itu tidak masalah. Masalah korsleting adalah detail level rendah yang hanya perlu Anda khawatirkan ketika berhadapan dengan kode kritis kinerja (aliran kontrol lambat). Saya akan lebih peduli dengan apa yang dimaksud dengan 'eksklusif atau' saat membuat operator logis darinya. Yakni, membuatnya beroperasi seperti versi bitwise (seperti operator lain), atau membuatnya menjadi atau eksklusif (sebanyak mungkin kondisi yang Anda inginkan, tetapi hanya satu yang benar).
Thorham
-3

Pertanyaan ini telah dijawab dengan efektif, tetapi saya menemukan situasi yang berbeda. Benar bahwa XOR bersyarat tidak diperlukan. Benar juga bahwa operator ^ dapat digunakan. Namun, jika Anda hanya perlu menguji status "true || false" dari operan maka ^ dapat menyebabkan masalah. Sebagai contoh:

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

Dalam contoh ini, jika kiri disetel ke 10 (0xa) dan kanan disetel ke 5 (0x5) cabang "sukses" dimasukkan. Untuk contoh ini (sederhana jika konyol), ini akan menghasilkan bug karena Anda tidak boleh berbelok ke kiri DAN kanan pada saat yang bersamaan. Apa yang saya kumpulkan dari penanya bukanlah bahwa dia sebenarnya menginginkan kondisional, tetapi cara sederhana untuk melakukan benar / salah pada nilai yang diteruskan ke xor.

Makro bisa melakukan trik:

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

Jangan ragu untuk menampar saya jika saya melenceng: o)

Saya membaca jawaban jimreed di bawah ini setelah saya memposting ini (Yapdog buruk!) Dan ini sebenarnya lebih sederhana. Itu akan berhasil dan saya sama sekali tidak tahu mengapa jawabannya ditolak ...

Yap Dog
sumber
3
Ini adalah pertanyaan C #, bukan C / C ++. ifmembutuhkan ekspresi Boolean, itu bahkan tidak akan dikompilasi dengan int.
Marc L.