Có phải là thực hành tốt để sử dụng toán tử xor cho kiểm tra boolean? [đóng cửa]


150

Cá nhân tôi thích toán tử độc quyền hoặc ,, ^khi nó có ý nghĩa trong bối cảnh kiểm tra boolean vì tính đồng nhất của nó. Tôi rất thích viết

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

hơn

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

nhưng tôi thường nhận được những cái nhìn bối rối từ các nhà phát triển Java có kinh nghiệm khác (không chỉ những người mới) và đôi khi nhận xét về cách nó chỉ nên được sử dụng cho các hoạt động theo bit.

Tôi tò mò về các thực tiễn tốt nhất về việc sử dụng ^toán tử.

Câu trả lời:


298

Bạn chỉ có thể sử dụng !=thay thế.


36
"Có gì sai với! =" Có bool1 ^ bool2 ^ bool3 ý nghĩa logic với tôi hơnbool1 != bool2 != bool3
BlueRaja - Danny Pflughoeft

4
Não tôi đau. Vậy có thể! = Mang lại kết quả không chính xác hay không?
vemv

27
@vemv, !=mang lại kết quả chính xác cho booleans (nhưng không phải cho Booleans vì vậy hãy cẩn thận). Nó không phải lúc nào cũng đẹp, ví dụ như (some != null) != (other != null)không dễ đọc. Bạn có thể phải trích xuất các phần trong booleans rõ ràng hoặc trích xuất phần đó !=trong một phương thức riêng biệt.
ngà

23
Đây là lý do: a ^ b=> "a hoặc b nhưng không phải cả hai", a != b=> "a không bằng b". (Những gì @RobertGrant nói). Hầu hết mọi người sẽ hiểu điều đầu tiên dễ dàng hơn nếu họ biết xor là gì (điều này khá hữu ích để biết nếu bạn ở trong lĩnh vực điện toán ...)
Harold R. Eason

2
@ HaroldR.Eason nitpicking quan trọng ở đây: a != b=> "a không phải là SẮC ĐẾN b"
Mario Reutter

27

Tôi nghĩ rằng bạn đã trả lời câu hỏi của riêng bạn - nếu bạn nhận được ánh mắt lạ từ mọi người, có lẽ sẽ an toàn hơn khi đi với tùy chọn rõ ràng hơn.

Nếu bạn cần bình luận, thì có lẽ tốt hơn hết bạn nên thay thế nó bằng phiên bản dài dòng hơn và không khiến mọi người đặt câu hỏi ngay từ đầu.


6
Tôi có thể khẳng định với bạn, bạn sẽ nhận được những cái nhìn lạ từ tôi, khi bạn nghiêm túc viết (boolean1 && !boolean2) || (boolean2 && !boolean1)trong một ứng dụng thực tế mã Mã
Holger

17

Tôi thấy rằng tôi có những cuộc trò chuyện tương tự rất nhiều. Một mặt, bạn có một phương pháp nhỏ gọn, hiệu quả để đạt được mục tiêu của mình. Mặt khác, bạn có một cái gì đó mà phần còn lại của nhóm bạn có thể không hiểu, khiến nó khó duy trì trong tương lai.

Nguyên tắc chung của tôi là hỏi xem kỹ thuật đang được sử dụng có phải là điều hợp lý để mong đợi các lập trình viên nói chung biết. Trong trường hợp này, tôi nghĩ rằng thật hợp lý khi mong đợi các lập trình viên biết cách sử dụng các toán tử boolean, vì vậy sử dụng xor trong một câu lệnh if là ổn.

Để làm ví dụ về điều gì đó sẽ không ổn, hãy sử dụng mẹo sử dụng xor để hoán đổi hai biến mà không sử dụng biến tạm thời. Đó là một mẹo mà tôi không mong đợi mọi người quen thuộc, vì vậy nó sẽ không vượt qua đánh giá mã.


14

Tôi nghĩ sẽ ổn thôi nếu bạn bình luận, vd // ^ == XOR.


10

Bạn luôn có thể bọc nó trong một hàm để đặt cho nó một tên dài dòng:

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

Nhưng, đối với tôi, dường như sẽ không khó cho những ai không biết nhà điều hành ^ làm gì cho Google nó thực sự nhanh chóng. Nó sẽ không khó để nhớ sau lần đầu tiên. Vì bạn đã yêu cầu sử dụng khác, nên thường sử dụng XOR cho mặt nạ bit.

Bạn cũng có thể sử dụng XOR để trao đổi các giá trị trong hai biến mà không cần sử dụng biến tạm thời thứ ba .

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

Đây là một câu hỏi Stackoverflow liên quan đến hoán đổi XOR .


6

Gần đây tôi đã sử dụng một xor trong một dự án JavaScript tại nơi làm việc và cuối cùng đã thêm 7 dòng bình luận để giải thích những gì đang diễn ra. Sự biện minh cho việc sử dụng xor trong bối cảnh đó là một trong những điều kiện ( term1trong ví dụ dưới đây) có thể kéo dài trên không phải là hai nhưng ba giá trị: undefined, truehoặc falsetrong khi người kia ( term2) có thể là truehay false. Tôi đã phải thêm một kiểm tra bổ sung cho các undefinedtrường hợp nhưng với xor, những điều sau đây là đủ vì xor buộc thuật ngữ đầu tiên được đánh giá đầu tiên là Boolean, undefinedhãy xử lý như falsesau:

if (term1 ^ term2) { ...

Cuối cùng, nó là một chút quá mức, nhưng dù sao tôi cũng muốn giữ nó ở đó, như một quả trứng Phục sinh.


IMHO, thay vì dựa vào chuyển đổi ngầm, trong tình huống bất thường gặp phải, tốt hơn là thực hiện chuyển đổi rõ ràng . Và nói chung, "để cho không xác định được coi là sai" là một thực tiễn đáng nghi ngờ trong bất kỳ ngôn ngữ nào. Tôi chưa sử dụng các giá trị ba trạng thái trong java, nhưng trong C #, một bool? agiá trị rõ ràng có thể được kiểm tra bằng cách sử dụng đúng a == true- có một kỹ thuật tương tự trong java không? Trong C #, được đưa ra hai bool?giá trị, "coi null là sai" sẽ dẫn đến (a == true) ^ (b == true). Một công thức tương đương là (a == true) != (b == true). Bạn có thể làm một cái gì đó tương tự trong java?
ToolmakerSteve

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

IMHO mã này có thể được đơn giản hóa:

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

5

Với sự rõ ràng về mã, ý kiến ​​của tôi là việc sử dụng XOR trong kiểm tra boolean không phải là cách sử dụng điển hình cho toán tử bit bit XOR. Theo kinh nghiệm của tôi, XOR bitwise trong Java thường được sử dụng để thực hiện flag togglehành vi mặt nạ :

flags = flags ^ MASK;

Bài viết này của Vipan Singla giải thích chi tiết hơn về trường hợp sử dụng.

Nếu bạn cần sử dụng XOR bitwise như trong ví dụ của mình, hãy nhận xét lý do tại sao bạn sử dụng nó, vì có khả năng yêu cầu ngay cả một khán giả biết chữ bit bit dừng theo dõi để hiểu lý do tại sao bạn sử dụng nó.


-1

Cá nhân tôi thích biểu thức "boolean1 ^ boolean2" do tính cô đọng của nó.

Nếu tôi ở trong hoàn cảnh của bạn (làm việc trong một nhóm), tôi sẽ thỏa hiệp bằng cách gói logic "boolean1 ^ boolean2" trong một hàm có tên mô tả như "isDifferent (boolean1, boolean2)".

Ví dụ: thay vì sử dụng "boolean1 ^ boolean2", bạn sẽ gọi "isDifferent (boolean1, boolean2)" như vậy:

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

Hàm "isDifferent (boolean1, boolean2)" của bạn sẽ trông như sau:

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

Tất nhiên, giải pháp này đòi hỏi phải sử dụng một lệnh gọi hàm ngoài có vẻ bề ngoài, bản thân nó phải chịu sự giám sát của Thực tiễn Tốt nhất, nhưng nó tránh được biểu thức dài dòng (và xấu xí) "(boolean1 &&! Boolean2) || (boolean2 &&! Boolean2) "!


-2

Nếu mô hình sử dụng biện minh cho nó, tại sao không? Trong khi nhóm của bạn không nhận ra nhà điều hành ngay lập tức, với thời gian họ có thể. Con người học từ mới mọi lúc. Tại sao không có trong lập trình?

Sự thận trọng duy nhất tôi có thể nói là "^" không có ngữ nghĩa ngắn mạch của kiểm tra boolean thứ hai của bạn. Nếu bạn thực sự cần ngữ nghĩa ngắn mạch, thì một phương thức sử dụng tĩnh cũng hoạt động.

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

16
Tôi không thấy bất kỳ sự cố ngắn mạch nào có thể xảy ra với xor - bạn phải biết cả a và b để đánh giá kết quả.
Thelema

7
Ngoài ra, các đối số sẽ được đánh giá thời gian cuộc gọi att, do đó không xảy ra ngắn mạch.
erikkallen

3
Ngoài ra, xor phải là một hoạt động đơn lẻ ở cấp độ máy.
Ogre Psalm33 18/03/13

Có lẽ bạn nên tìm kiếm sự khác biệt giữa đánh giá ngắn mạch và đánh giá lười biếng. Đánh giá curcuit ngắn là một kiểu mã ngăn chặn các cuộc gọi có thể dẫn đến lỗi thời gian chạy, chẳng hạn như chia cho số không. Trong C, đây có thể là ´ifif (mẫu số! = 0 && tử số / mẫu số) iên, trong đó tự sử dụng đánh giá lười biếng để ngăn chia cho 0. Câu trả lời của bạn cũng hoàn toàn là suy đoán.
Martin

2
Thành thật mà nói, một lập trình viên viết một hàm xor, thực hiện chính xác những gì toán tử xor làm nhưng theo cách vòng, sẽ đưa ra nhiều câu hỏi trong đầu tôi (cụ thể là về năng lực) so với lập trình viên vừa sử dụng ^.
Stijn de Witt

-3

! = OK để so sánh hai biến. Nó không hoạt động, mặc dù, với nhiều so sánh.


-3

Là một toán tử bitwise, xor nhanh hơn nhiều so với bất kỳ phương tiện nào khác để thay thế nó. Vì vậy, đối với hiệu suất quan trọng và khả năng mở rộng, xor là bắt buộc.

Ý kiến ​​cá nhân chủ quan của tôi: Nghiêm cấm sử dụng quyền bình đẳng (== hoặc! =) Cho booleans. Sử dụng nó cho thấy thiếu đạo đức lập trình cơ bản và các nguyên tắc cơ bản. Bất cứ ai mang đến cho bạn vẻ bối rối ^ nên được gửi lại những điều cơ bản của đại số boolean (tôi đã cố viết "đến dòng sông niềm tin" ở đây :)).


1
Ngoại trừ việc JIT cực kỳ tốt trong việc tối ưu hóa lỗ khóa (ít), như thay thế một biểu thức boolean bằng một biểu thức boolean khác.
David Leppik

1
Ngoài ra, ^ chủ yếu không phải là toán tử Boolean (logic), nó là toán tử bitwise. Nó bảo người đọc chậm lại, vì có khả năng là có dấu hiệu lỗi. Nếu bạn sử dụng ^ for! =, Bạn sẽ thực sự gặp rắc rối nếu bạn từng lập trình trong C. Toán tử bitwise là tín hiệu cho độc giả của bạn (những người gỡ lỗi mã của bạn, bao gồm cả bạn) để làm chậm và tìm lỗi ký hiệu . Và họ có thể khó khăn. Ví dụ, bạn có biết rằng% của Java không phải là modulo đúng, như trong C hoặc Python không? Tôi đã từng có một đoạn mã chạy giống nhau trong C, JavaScript và Python, nhưng không phải trong Java.
David Leppik

6
Làm thế nào điều này bao giờ được nâng cấp? Trước hết, trong Java XOR và! = Được biên dịch [ stackoverflow.com/a/4175512/202504THER( để có cùng mã chính xác), thứ hai ngay cả trong kiểm tra trình biên dịch mã cho đẳng thức và xor là mỗi thao tác đơn giản. Bạn có bất kỳ số để sao lưu tuyên bố của bạn?
jmiserez

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

có vẻ tốt cho tôi hơn

str.contains("!=") != str.startsWith("not(")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.