Apakah praktik yang baik untuk menggunakan operator xor untuk pemeriksaan boolean? [Tutup]


150

Saya pribadi suka operator eksklusif atau , ^ketika masuk akal dalam konteks pemeriksaan boolean karena keringkasannya. Saya lebih suka menulis

if (boolean1 ^ boolean2)
{
  //do it
}

dari

if((boolean1 && !boolean2) || (boolean2 && !boolean1))
{
  //do it
}

tapi saya sering bingung melihat dari pengembang Java berpengalaman lainnya (bukan hanya pemula), dan kadang-kadang komentar tentang bagaimana seharusnya hanya digunakan untuk operasi bitwise.

Saya ingin tahu tentang praktik terbaik terkait penggunaan ^operator.

Jawaban:


298

Anda bisa menggunakan !=saja.


36
"Ada apa dengan! =" bool1 ^ bool2 ^ bool3 Lebih masuk akal bagiku daripadabool1 != bool2 != bool3
BlueRaja - Danny Pflughoeft

4
Otakku sakit. Jadi bisakah! = Menghasilkan hasil yang salah atau tidak?
vemv

27
@ vemv, !=menghasilkan hasil yang benar untuk booleans (tetapi tidak untuk Booleans jadi hati-hati). Ini tidak selalu cantik, misalnya (some != null) != (other != null)tidak terlalu mudah dibaca. Anda juga harus mengekstrak bagian-bagian dalam boolean eksplisit, atau mengekstraknya !=dalam metode terpisah.
ivant

23
Inilah sebabnya: a ^ b=> "a atau b tetapi tidak keduanya", a != b=> "a tidak sama dengan b". (Apa yang dikatakan @RobertGrant). Sebagian besar manusia akan lebih mudah memahami yang pertama jika mereka tahu apa itu xor (yang cukup berguna untuk mengetahui apakah Anda berada di bidang komputasi ...)
Harold R. Eason

2
@ HaroldR. Alasan penting nitpicking di sini: a != b=> "a tidak IDENTIK untuk b"
Mario Reutter

27

Saya pikir Anda telah menjawab pertanyaan Anda sendiri - jika Anda mendapat tampilan aneh dari orang lain, mungkin lebih aman untuk menggunakan opsi yang lebih eksplisit.

Jika Anda perlu berkomentar, maka Anda mungkin lebih baik menggantinya dengan versi yang lebih verbose dan tidak membuat orang bertanya terlebih dahulu.


6
Saya dapat menegaskan Anda, Anda akan mendapatkan tampilan aneh dari saya, ketika Anda serius menulis (boolean1 && !boolean2) || (boolean2 && !boolean1)dalam kode aplikasi kehidupan nyata ...
Holger

17

Saya menemukan banyak percakapan serupa. Di satu sisi, Anda memiliki metode yang kompak, efisien untuk mencapai tujuan Anda. Di sisi lain, Anda memiliki sesuatu yang mungkin tidak dimengerti oleh anggota tim Anda lainnya, sehingga sulit untuk dipertahankan di masa depan.

Aturan umum saya adalah menanyakan apakah teknik yang digunakan adalah sesuatu yang masuk akal untuk diketahui oleh programmer secara umum. Dalam hal ini, saya pikir masuk akal untuk mengharapkan pemrogram mengetahui cara menggunakan operator boolean, jadi menggunakan xor dalam pernyataan if tidak apa-apa.

Sebagai contoh dari sesuatu yang tidak akan apa-apa, ambil trik menggunakan xor untuk bertukar dua variabel tanpa menggunakan variabel sementara. Itu adalah trik yang saya tidak berharap semua orang akan terbiasa, sehingga tidak akan melewati tinjauan kode.


14

Saya pikir tidak apa-apa jika Anda berkomentar, misalnya // ^ == XOR.


10

Anda selalu bisa membungkusnya dalam suatu fungsi untuk memberikannya nama verbal:

public static boolean XOR(boolean A, boolean B) {
    return A ^ B;
}

Tetapi, bagi saya tampaknya tidak akan sulit bagi siapa pun yang tidak tahu apa artinya operator bagi Google dengan sangat cepat. Tidak akan sulit untuk diingat setelah pertama kali. Karena Anda meminta kegunaan lain, biasanya menggunakan XOR untuk masking bit.

Anda juga dapat menggunakan XOR untuk menukar nilai dalam dua variabel tanpa menggunakan variabel sementara ketiga .

// Swap the values in A and B
A ^= B;
B ^= A;
A ^= B;

Inilah pertanyaan Stackoverflow terkait dengan pertukaran XOR .


6

Saya baru-baru ini menggunakan xor dalam proyek JavaScript di kantor dan akhirnya menambahkan 7 baris komentar untuk menjelaskan apa yang terjadi. Pembenaran untuk menggunakan XOR dalam konteks itu adalah bahwa salah satu syarat ( term1pada contoh di bawah) bisa mengambil bukan dua tapi tiga nilai: undefined, trueatau falsesementara yang lain ( term2) bisa trueatau false. Saya harus menambahkan pemeriksaan tambahan untuk undefinedkasus - kasus tetapi dengan xor, berikut ini sudah cukup karena xor memaksa istilah pertama yang pertama kali dievaluasi sebagai Boolean, membiarkan undefineddiperlakukan sebagai false:

if (term1 ^ term2) { ...

Pada akhirnya, itu sedikit berlebihan, tapi aku tetap ingin tetap di sana, sebagai semacam telur paskah.


IMHO, daripada mengandalkan konversi implisit, dalam situasi yang tidak biasa ditemui, lebih baik membuat konversi eksplisit . Dan secara umum, "membiarkan yang tidak terdefinisi diperlakukan sebagai salah" adalah praktik yang dipertanyakan dalam bahasa apa pun. Saya belum pernah menggunakan nilai tri-state di java, tetapi di C #, sebuah bool? anilai dapat secara eksplisit diuji untuk benar menggunakan a == true- apakah ada teknik serupa di java? Dalam C #, diberikan dua bool?nilai, "perlakukan null sebagai salah" akan mengarah ke (a == true) ^ (b == true). Formula setara adalah (a == true) != (b == true). Bisakah Anda melakukan hal serupa di java?
ToolmakerSteve

5
if((boolean1 && !boolean2) || (boolean2 && !boolean1)) 
{ 
  //do it 
} 

IMHO kode ini dapat disederhanakan:

if(boolean1 != boolean2) 
{ 
  //do it 
} 

5

Dengan kejelasan kode dalam pikiran, pendapat saya adalah bahwa menggunakan XOR dalam pemeriksaan boolean bukanlah penggunaan khas untuk operator bitwise XOR. Dari pengalaman saya, bitwise XOR di Jawa biasanya digunakan untuk menerapkan flag toggleperilaku topeng :

flags = flags ^ MASK;

Artikel ini oleh Vipan Singla menjelaskan kasus penggunaan lebih detail.

Jika Anda perlu menggunakan bitwise XOR seperti dalam contoh Anda, beri komentar mengapa Anda menggunakannya, karena itu mungkin membutuhkan audiens yang sedikit melek huruf untuk berhenti di jalurnya untuk memahami mengapa Anda menggunakannya.


-1

Saya pribadi lebih suka ekspresi "boolean1 ^ boolean2" karena ringkasnya.

Jika saya berada dalam situasi Anda (bekerja dalam tim), saya akan melakukan kompromi dengan merangkum logika "boolean1 ^ boolean2" dalam sebuah fungsi dengan nama deskriptif seperti "isDifferent (boolean1, boolean2)".

Misalnya, alih-alih menggunakan "boolean1 ^ boolean2", Anda akan memanggil "isDifferent (boolean1, boolean2)" seperti:

if (isDifferent(boolean1, boolean2))
{
  //do it
}

Fungsi "isDifferent (boolean1, boolean2)" Anda akan terlihat seperti:

private boolean isDifferent(boolean1, boolean2)
{
    return boolean1 ^ boolean2;
}

Tentu saja, solusi ini memerlukan penggunaan pemanggilan fungsi yang tampaknya asing, yang dengan sendirinya tunduk pada pengawasan Praktik Terbaik, tetapi ia menghindari ekspresi verbose (dan jelek) "(boolean1 &&! Boolean2) || (boolean2 &&! Boolean1) "!


-2

Jika pola penggunaan membenarkannya, mengapa tidak? Sementara tim Anda tidak mengenali operator segera, dengan waktu yang mereka bisa. Manusia belajar kata-kata baru setiap saat. Kenapa tidak dalam pemrograman?

Satu-satunya peringatan yang mungkin saya nyatakan adalah "^" tidak memiliki semantik hubung singkat dari cek boolean kedua Anda. Jika Anda benar-benar membutuhkan semantik hubung singkat, maka metode util statis juga berfungsi.

public static boolean xor(boolean a, boolean b) {
    return (a && !b) || (b && !a);
}

16
Saya tidak melihat hubungan arus pendek yang dimungkinkan dengan xor - Anda harus mengetahui a dan b untuk mengevaluasi hasilnya.
Thelema

7
Juga, argumen akan dievaluasi untuk waktu panggilan, jadi tidak ada hubungan arus pendek yang akan terjadi.
erikkallen

3
Selain itu, xor harus menjadi operasi tunggal di level mesin.
Ogre Psalm33

Anda mungkin harus mencari perbedaan antara evaluasi hubung singkat dan evaluasi malas. Evaluasi short-curcuit adalah gaya kode yang mencegah panggilan yang jika tidak akan menghasilkan kesalahan runtime, seperti pembagian dengan nol. Dalam C ini bisa menjadi ´jika (penyebut! = 0 && pembilang / penyebut) ´, yang di dalamnya menggunakan evaluasi malas untuk mencegah pembagian dengan nol. Jawaban Anda juga murni spekulatif.
Martin

2
Sejujurnya, seorang programmer yang menulis suatu fungsi xor, yang melakukan persis apa yang dilakukan oleh operator xor tetapi secara tidak langsung, akan memunculkan lebih banyak pertanyaan dalam pikiran saya (khususnya tentang kompetensi) daripada seorang programmer yang baru saja digunakan ^.
Stijn de Witt

-3

! = OK untuk membandingkan dua variabel. Namun, itu tidak berfungsi dengan beberapa perbandingan.


-3

Sebagai operator bitwise, xor jauh lebih cepat daripada cara lain untuk menggantinya. Jadi untuk perhitungan kritis dan terukur kinerja, xor sangat penting.

Pendapat pribadi subjektif saya: Sangat dilarang, untuk tujuan apa pun, untuk menggunakan kesetaraan (== atau! =) Untuk boolean. Menggunakannya menunjukkan kurangnya etika pemrograman dasar dan fundamental. Siapa pun yang memberi Anda pandangan bingung ^ harus dikirim kembali ke dasar-dasar aljabar boolean (saya tergoda untuk menulis "ke sungai kepercayaan" di sini :)).


1
Kecuali bahwa JIT sangat bagus dalam optimasi lubang kunci (kecil), seperti mengganti satu ekspresi boolean dengan yang lain.
David Leppik

1
Juga, ^ bukan terutama operator Boolean (logika), ini adalah operator bitwise. Ini memberitahu pembaca untuk memperlambat, karena ada kemungkinan ada bug tanda. Jika Anda menggunakan ^ for! =, Anda akan benar-benar kacau jika Anda pernah memprogram dalam C. Operator bitwise adalah sinyal bagi pembaca Anda (mereka yang men-debug kode Anda, termasuk Anda) untuk memperlambat dan mencari tanda kesalahan . Dan mereka bisa rumit. Sebagai contoh, apakah Anda tahu bahwa% Java tidak benar modulo, seperti di C atau Python? Saya pernah memiliki potongan kode yang menjalankan hal yang sama dalam C, JavaScript, dan Python, tetapi tidak di Jawa.
David Leppik

6
Bagaimana ini bisa terangkat? Pertama-tama, di Java XOR dan! = Dikompilasi [ stackoverflow.com/a/4175512/202504)(ke kode yang sama persis), kedua bahkan dalam pengujian assembler untuk kesetaraan dan xor adalah masing-masing operasi sederhana tunggal. Apakah Anda memiliki nomor untuk mendukung pernyataan Anda?
jmiserez

-4
str.contains("!=") ^ str.startsWith("not(")

terlihat lebih baik untukku daripada

str.contains("!=") != str.startsWith("not(")
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.