เป็นการดีที่จะใช้ตัวดำเนินการ xor สำหรับการตรวจสอบบูลีนหรือไม่? [ปิด]


150

ผมเองชอบแต่เพียงผู้เดียวหรือ , ^ผู้ประกอบการเมื่อมันทำให้ความรู้สึกในบริบทของการตรวจสอบแบบบูลเพราะความกระชับของตน ฉันชอบเขียนมาก

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

กว่า

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

แต่บ่อยครั้งที่ฉันรู้สึกสับสนจากนักพัฒนา Java คนอื่น (ไม่ใช่เฉพาะมือใหม่) และบางครั้งก็แสดงความคิดเห็นว่าควรใช้สำหรับการทำงานระดับบิตได้อย่างไร

ฉันอยากรู้วิธีปฏิบัติที่ดีที่สุดเกี่ยวกับการใช้งานของ^ผู้ให้บริการ

คำตอบ:


298

คุณสามารถใช้!=แทน


36
"เกิดอะไรขึ้นกับ! =" bool1 ^ bool2 ^ bool3ทำให้ฉันมีเหตุผลมากกว่าตรรกะbool1 != bool2 != bool3
BlueRaja - Danny Pflughoeft

4
สมองของฉันเจ็บ ดังนั้น! = ให้ผลลัพธ์ที่ไม่ถูกต้องหรือไม่?
vemv

27
@vemv ให้!=ผลลัพธ์ที่ถูกต้องสำหรับbooleans (แต่ไม่ใช่Booleans ดังนั้นโปรดระวัง) มันไม่ได้สวยเสมอไปตัวอย่างเช่น (some != null) != (other != null)อ่านไม่ได้ คุณอาจจะต้องแยกส่วนต่าง ๆ ใน booleans ชัดเจนหรือแยก!=ในวิธีแยกต่างหาก
ivant

23
นี่คือเหตุผล: a ^ b=> "a หรือ b แต่ไม่ใช่ทั้งสอง", a != b=> "a ไม่เท่ากับ b" (@RobertGrant พูดอะไร) มนุษย์ส่วนใหญ่จะเข้าใจคนแรกได้ง่ายขึ้นถ้าพวกเขารู้ว่า xor คืออะไร (ซึ่งค่อนข้างมีประโยชน์ที่จะรู้ว่าคุณอยู่ในสาขาการคำนวณ ... )
Harold R. Eason

2
@ HaroldR. ให้ความสำคัญกับ nitpicking ที่นี่: a != b=> "a ไม่ใช่ตัวบ่งชี้ถึง b"
Mario Reutter

27

ฉันคิดว่าคุณตอบคำถามของคุณเอง - ถ้าคุณได้รับรูปลักษณ์ที่แปลกประหลาดจากผู้คนมันอาจจะปลอดภัยกว่าถ้ามีตัวเลือกที่ชัดเจนกว่านี้

หากคุณต้องการแสดงความคิดเห็นแสดงว่าคุณน่าจะดีกว่าที่จะแทนที่ด้วยรุ่น verbose ที่มากขึ้นและไม่ทำให้ผู้คนถามคำถามตั้งแต่แรก


6
ฉันสามารถยืนยันคุณคุณจะได้รับรูปลักษณ์ที่แปลกประหลาดจากฉันเมื่อคุณเขียน(boolean1 && !boolean2) || (boolean2 && !boolean1)โค้ดแอปพลิเคชันในชีวิตจริงอย่างจริงจัง...
Holger

17

ฉันพบว่าฉันมีการสนทนาที่คล้ายกันมาก ในอีกด้านหนึ่งคุณมีวิธีการที่กะทัดรัดและมีประสิทธิภาพในการบรรลุเป้าหมายของคุณ ในทางกลับกันคุณมีบางอย่างที่คนอื่น ๆ ในทีมอาจไม่เข้าใจทำให้ยากที่จะดูแลในอนาคต

กฎทั่วไปของฉันคือการถามว่าเทคนิคการใช้เป็นสิ่งที่เหมาะสมที่จะคาดหวังโปรแกรมเมอร์โดยทั่วไปที่จะรู้ ในกรณีนี้ฉันคิดว่ามันสมเหตุสมผลที่จะคาดหวังว่าโปรแกรมเมอร์จะรู้วิธีใช้ตัวดำเนินการบูลีนดังนั้นการใช้ xor ในคำสั่ง if จะไม่เป็นไร

เป็นตัวอย่างของสิ่งที่ไม่เป็นไรใช้เคล็ดลับในการใช้ xor เพื่อสลับสองตัวแปรโดยไม่ต้องใช้ตัวแปรชั่วคราว นั่นเป็นกลลวงที่ฉันไม่คาดหวังให้ทุกคนคุ้นเคยดังนั้นมันจะไม่ผ่านการตรวจสอบโค้ด


14

// ^ == XORผมคิดว่ามันจะโอเคถ้าคุณแสดงความคิดเห็นมันเช่น


10

คุณสามารถห่อมันในฟังก์ชั่นเพื่อตั้งชื่อให้ละเอียด:

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

แต่สำหรับฉันแล้วดูเหมือนว่ามันจะไม่เป็นเรื่องยากสำหรับคนที่ไม่รู้ว่าตัวดำเนินการ ^ สำหรับ Google นั้นรวดเร็วเพียงใด มันจะไม่ยากที่จะจำหลังจากครั้งแรก เมื่อคุณถามถึงการใช้งานอื่น ๆ มันเป็นเรื่องปกติที่จะใช้ XOR สำหรับการปิดบังบิต

นอกจากนี้คุณยังสามารถใช้แฮคเกอร์ที่จะแลกเปลี่ยนค่าในตัวแปรทั้งสองโดยไม่ต้องใช้ตัวแปรชั่วคราวที่สาม

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

นี่เป็นคำถาม Stackoverflow ที่เกี่ยวข้องกับการแฮคเกอร์แลกเปลี่ยน


6

ฉันเพิ่งใช้ xor ในโครงการ JavaScript ในที่ทำงานและจบลงด้วยการเพิ่มความคิดเห็น 7 บรรทัดเพื่ออธิบายสิ่งที่เกิดขึ้น เหตุผลสำหรับการใช้ xor ในบริบทที่เป็นหนึ่งในแง่ที่ว่า ( term1ในตัวอย่างด้านล่าง) จะใช้เวลาในการไม่ได้ แต่สองสามค่า: undefined, trueหรือfalseขณะที่อื่น ๆ ( term2) อาจจะเป็นหรือtrue falseฉันจะต้องเพิ่มการตรวจสอบเพิ่มเติมสำหรับundefinedกรณี แต่ด้วย xor ต่อไปนี้ก็เพียงพอเนื่องจาก xor บังคับให้คำแรกที่จะได้รับการประเมินครั้งแรกเป็นบูลีนให้undefinedได้รับการปฏิบัติfalseดังนี้:

if (term1 ^ term2) { ...

ในที่สุดมันก็เกินความเป็นไปได้นิดหน่อย แต่ฉันก็อยากจะเก็บมันไว้ในนั้นเหมือนเป็นไข่อีสเตอร์


IMHO แทนการพึ่งพาการแปลงโดยปริยายในสถานการณ์ที่ผิดปกติที่พบจะดีกว่าที่จะทำให้การแปลงอย่างชัดเจน และโดยทั่วไปการ "ปล่อยให้ undefined ถูกถือว่าเป็น false" เป็นแนวปฏิบัติที่น่าสงสัยในภาษาใด ๆ ฉันไม่ได้ใช้ค่า tri-state ใน java แต่ใน C # bool? aค่าสามารถทดสอบอย่างชัดเจนสำหรับการใช้งานจริงa == true- มีเทคนิคที่คล้ายกันใน java หรือไม่ ใน C #, รับสองbool?ค่า "null รักษาเป็นเท็จ" (a == true) ^ (b == true)จะนำไปสู่ (a == true) != (b == true)สูตรเทียบเท่า คุณสามารถทำสิ่งที่คล้ายกันใน java?
ToolmakerSteve

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

IMHO รหัสนี้สามารถลดความซับซ้อน:

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

5

ด้วยความชัดเจนของรหัสในความคิดของฉันคือการใช้ XOR ในการตรวจสอบบูลีนไม่ใช่การใช้งานทั่วไปสำหรับผู้ดำเนินการ XOR ในระดับบิต จากประสบการณ์ของฉัน bitwise XOR ใน Java โดยทั่วไปจะใช้ในการใช้งานรูปแบบflag toggleการทำงานของหน้ากาก:

flags = flags ^ MASK;

นี้บทความโดย Vipan Singla อธิบายกรณีการใช้งานมากขึ้นในรายละเอียด

หากคุณจำเป็นต้องใช้บิต XOR ในตัวอย่างของคุณแสดงความคิดเห็นว่าทำไมคุณถึงใช้เพราะอาจเป็นไปได้ที่ผู้ชมที่อ่านออกเขียนได้จะต้องหยุดอยู่ในเส้นทางของพวกเขาเพื่อทำความเข้าใจว่าทำไมคุณถึงใช้มัน


-1

ฉันชอบการแสดงออก "boolean1 ^ boolean2" เป็นการส่วนตัวเนื่องจากความรัดกุม

ถ้าฉันอยู่ในสถานการณ์ของคุณ (ทำงานเป็นทีม) ฉันจะประนีประนอมโดยการใส่ตรรกะ "boolean1 ^ boolean2" ในฟังก์ชันที่มีชื่อที่อธิบายเช่น "isDifferent (boolean1, boolean2)"

ตัวอย่างเช่นแทนที่จะใช้ "boolean1 ^ boolean2" คุณจะเรียกว่า "isDifferent (boolean1, boolean2)" เช่น:

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

ฟังก์ชัน "isDifferent (boolean1, boolean2)" ของคุณจะมีลักษณะดังนี้:

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

แน่นอนว่าวิธีนี้จะทำให้เกิดการใช้ฟังก์ชั่นการโทรจากภายนอกซึ่งในตัวมันเองนั้นเป็นไปตามแนวทางปฏิบัติที่ดีที่สุด แต่มันก็ช่วยหลีกเลี่ยงการแสดงออกอย่างชัดเจน (และน่าเกลียด) verbose (boolean1 &&! boolean2) "!


-2

หากรูปแบบการใช้งานนั้นเหมาะสมทำไมถึงเป็นเช่นนั้น? ในขณะที่ทีมของคุณไม่รู้จักตัวดำเนินการทันทีด้วยเวลาเท่าที่จะทำได้ มนุษย์เรียนรู้คำศัพท์ใหม่ตลอดเวลา ทำไมไม่เขียนโปรแกรม?

ข้อควรระวังข้อเดียวที่ฉันอาจระบุได้คือ "^" ไม่มีความหมายสั้น ๆ ของการตรวจสอบบูลีนครั้งที่สองของคุณ หากคุณต้องการความหมายของไฟฟ้าลัดวงจรจริงๆแล้ววิธี static util ก็จะทำงานเช่นกัน

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

16
ฉันไม่เห็นการลัดวงจรใด ๆ ที่เป็นไปได้ด้วย xor - คุณต้องรู้ทั้ง a และ b เพื่อประเมินผลลัพธ์
Thelema

7
นอกจากนี้ข้อโต้แย้งจะถูกประเมินเวลาเรียกใช้ดังนั้นจะไม่มีการลัดวงจรเกิดขึ้น แต่อย่างใด
erikkallen

3
นอกจากนี้ xor ควรเป็นการทำงานเดี่ยวที่ระดับเครื่อง
Ogre Psalm33

คุณควรค้นหาความแตกต่างระหว่างการประเมินการลัดวงจรและการประเมินผลที่ขี้เกียจ การประเมินผลแบบระยะสั้นเป็นรูปแบบรหัสที่ป้องกันการโทรที่อาจทำให้เกิดข้อผิดพลาดรันไทม์เช่นการหารด้วยศูนย์ ใน C นี่อาจเป็น´if (ตัวส่วน! = 0 && ตัวเศษ / ตัวส่วน) ´ซึ่งมันใช้การประเมินแบบขี้เกียจเพื่อป้องกันการหารด้วยศูนย์ คำตอบของคุณคือการเก็งกำไรอย่างหมดจด
Martin

2
จะซื่อสัตย์โปรแกรมเมอร์เขียนฟังก์ชั่นxorที่ไม่ตรงกับสิ่งที่ผู้ประกอบการ xor ไม่ แต่ในทางอ้อมจะนำมาซึ่งคำถามมากขึ้นในใจของฉัน (เฉพาะที่เกี่ยวกับความสามารถ) ^มากกว่าโปรแกรมเมอร์ที่ใช้เพียง
Stijn de Witt

-3

! = is OK เพื่อเปรียบเทียบสองตัวแปร แม้ว่ามันจะไม่ทำงานแม้ว่าจะมีการเปรียบเทียบหลายแบบก็ตาม


-3

ในฐานะผู้ประกอบการระดับบิต xor นั้นเร็วกว่าวิธีอื่น ๆ ในการแทนที่ ดังนั้นสำหรับการคำนวณเชิงประสิทธิภาพและปรับขนาดได้ xor จึงมีความจำเป็น

ความคิดเห็นส่วนตัวที่เป็นส่วนตัวของฉัน: ห้ามมิให้มีการใช้ความเสมอภาค (== หรือ! =) สำหรับ booleans อย่างเด็ดขาด การใช้มันแสดงให้เห็นถึงการขาดจริยธรรมการเขียนโปรแกรมพื้นฐานและพื้นฐาน ใครก็ตามที่ทำให้คุณดูสับสน ^ ควรถูกส่งกลับไปที่พื้นฐานของพีชคณิตแบบบูล (ฉันถูกล่อลวงให้เขียน "ไปที่แม่น้ำแห่งความเชื่อ" ที่นี่ :))


1
ยกเว้นว่า JIT นั้นดีมากในการเพิ่มประสิทธิภาพรูกุญแจ (เล็กน้อย) เช่นการแทนที่นิพจน์บูลีนหนึ่งด้วยนิพจน์อื่น
David Leppik

1
^ เป็นหลักไม่ได้เป็นผู้ประกอบการบูลีน (ตรรกะ) มันเป็นผู้ประกอบการระดับบิต มันบอกผู้อ่านให้ชะลอตัวลงเพราะมีแนวโน้มที่จะมีการลงนามข้อบกพร่อง ถ้าคุณใช้ ^ for! = คุณจะสับสนถ้าคุณเคยเขียนโปรแกรมใน C. ผู้ดำเนินการ Bitwise เป็นสัญญาณให้กับผู้อ่านของคุณ (ผู้ที่ดีบักรหัสของคุณรวมถึงคุณ) เพื่อชะลอและมองหาข้อผิดพลาดของเครื่องหมาย . และพวกเขาอาจเป็นเรื่องยุ่งยาก ตัวอย่างเช่นคุณรู้หรือไม่ว่า% ของ Java นั้นไม่ใช่โมดูโล่ที่แท้จริงเช่นใน C หรือ Python ฉันเคยมีตัวอย่างของรหัสที่ทำงานเหมือนกันใน C, JavaScript และ Python แต่ไม่ใช่ใน Java
David Leppik

6
สิ่งนี้ได้รับการโหวตอย่างไร ประการแรกใน Java XOR และ! = จะรวบรวม [ stackoverflow.com/a/4175512/202504เหมือนกัน (สำหรับรหัสเดียวกันที่แน่นอน) ที่สองแม้ในการทดสอบแอสเซมเบลอร์สำหรับความเท่าเทียมกันและ xor เป็นการดำเนินการอย่างง่าย ๆ เพียงครั้งเดียว คุณมีหมายเลขใดบ้างที่จะสำรองคำสั่งของคุณ?
jmiserez

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.