XOR có điều kiện?


87

Tại sao C # không có XORtoán tử điều kiện ?

Thí dụ:

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

15
Làm thế nào để !=hoạt động như một chất thay thế?
Pascal Cuoq

45
C # không có toán tử xor (x ^ y). Do đó tôi phủ nhận tiền đề của câu hỏi. Bạn có thể giải thích tại sao bạn tin rằng C # không có toán tử xor? Tôi muốn tìm hiểu lý do tại sao mọi người tin những điều sai lệch về C #.
Eric Lippert

3
@Eric Lippert: Tôi nghĩ anh ấy đang đề cập đến toán tử logic ( & | ^) so với toán tử điều kiện ( && ||). Nhưng bạn đúng (tất nhiên), có một XOR hợp lý ...
BoltClock

14
@BoltClock: Ồ, nếu câu hỏi là "tại sao không có toán tử xor đoản mạch?" - làm thế nào có thể có? Với "và" nếu đối số đầu tiên là sai, bạn không cần đánh giá đối số thứ hai. Với "hoặc", nếu đối số đầu tiên là đúng thì bạn không cần đánh giá đối số thứ hai. Bạn luôn cần đánh giá cả hai đối số cho xor, vì vậy không thể xảy ra hiện tượng đoản mạch.
Eric Lippert

4
Bản thân câu hỏi phù hợp hơn với Microsoft - và vì vậy đó là lý do chính đáng để phản đối - nhưng nếu bất cứ ai phản đối nó đã làm như vậy vì toán tử ^, thì bạn cần phải đọc chú ý hơn đến chi tiết, bởi vì câu hỏi có điều kiện so với. hợp lý, không chỉ đơn giản là "tại sao không có XOR".
The Evil Greebo

Câu trả lời:


121

Trong C #, các toán tử có điều kiện chỉ thực hiện toán hạng phụ của chúng nếu cần thiết .

Vì một XOR theo định nghĩa phải kiểm tra cả hai giá trị, một phiên bản có điều kiện sẽ là ngớ ngẩn.

Ví dụ :

  • Logic AND: &- kiểm tra cả hai mặt mọi lúc.

  • Hợp lý HOẶC: |- kiểm tra cả hai mặt mọi lúc.

  • AND có điều kiện: &&- chỉ kiểm tra vế thứ 2 nếu vế thứ nhất là đúng.

  • HOẶC có điều kiện: ||- chỉ kiểm tra mặt thứ 2 nếu mặt thứ nhất là sai.


35
Một toán tử XOR sẽ không vi phạm quy ước "các toán tử có điều kiện chỉ thực hiện toán hạng phụ nếu cần". Nó sẽ luôn luôn cần thiết.
Nathan Kovner

2
XOR có điều kiện có thể là một phím tắt đẹp và trang nhã cho một số mẫu cụ thể, mặc dù không chắc liệu có đủ hợp lý để đưa nó vào ngôn ngữ hay không. Một ví dụ về các mẫu như vậy mà XOR có thể tỏ ra hữu ích, là Phủ định có điều kiện: Khi một biểu thức Boolean có nên bị phủ định hay không, hãy cho một biểu thức boolean thứ hai.
SalvadorGomez

1
Tôi đã không phản hồi điều này trong một thời gian nhưng để trả lời nhận xét phổ biến của @KhyadHalda: Tại sao bạn lại xây dựng một thứ mà bạn biết sẽ không bao giờ được sử dụng? Bạn đang cố tình viết mã chết.
The Evil Greebo

Cho rằng một toán tử XOR có điều kiện sẽ không vi phạm quy ước mà bạn xác định (nhận xét của Khyad), cùng với thực tế là nó thực sự hữu ích trong một số trường hợp, nó phủ nhận khá nhiều "sự ngu ngốc" mà bạn gán cho một toán tử như vậy hiện có.
Syndog

1
Làm thế nào, bao giờ, một XOR có điều kiện sẽ hữu ích? Một XOR có điều kiện không thể đánh giá nếu không so sánh cả hai bên để xác định rằng chúng ngang bằng hoặc không bằng nhau. Ngay cả khái niệm XOR có điều kiện so sánh hai bool vẫn phải kiểm tra giá trị của từng bool và kiểm tra sự bằng nhau.
The Evil Greebo

280

Câu hỏi hơi lỗi thời nhưng ...

Đó là cách toán tử này hoạt động:

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

Đây là cách toán tử! = Hoạt động với các kiểu bool:

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

Vì vậy, như bạn thấy ^^không tồn tại có thể được thay thế bằng!=


46
Đây thực sự là câu trả lời duy nhất giải quyết câu hỏi một cách trực tiếp và chính xác.
usr

39
Tôi đang ngồi đây đối mặt với bản thân rằng tôi đã không nhận ra !=sẽ làm việc cho điều này.
AdamMc331

1
Câu trả lời là đúng nhưng các ý kiến ​​thì không. Nó không giải quyết câu hỏi, đó là "tại sao C # không có XOR có điều kiện?". Nói một cách chính xác, đây không phải là một toán tử logic, nó là một toán tử bình đẳng quan hệ. Mặc dù kết quả giống như XOR, nhưng nó ở một lớp khác. Nó chỉ so sánh với XOR khi kiểm tra hai giá trị boolean và cả hai mặt của toán tử vẫn phải được đánh giá.
The Evil Greebo

3
@TheEvilGreebo - Điều bạn nói là đúng; toán tử! = về mặt kỹ thuật không phải là toán tử XOR có điều kiện. Tuy nhiên, câu trả lời này nói một cách hiệu quả, "Một toán tử XOR có điều kiện không tồn tại bởi vì toán tử! = Có." Đó là cách tôi đọc nó, dù sao.
Syndog

6
Tôi nghĩ rằng hầu hết mọi người kết thúc bài đăng này thực sự muốn viết XOR trên Booleans. giống như có logic ANDORnhưng không có gì như XOR. hoặc ít nhất là chúng tôi đã không nhận ra !=:) @TheEvilGreebo
M.kazem Akhgary

30

Có toán tử XOR logic: ^

Tài liệu: Các toán tử C #^ Toán tử


2
Hợp lý, không có điều kiện. Hợp lý và = &, có điều kiện và = &&. Anh ấy đang hỏi về Điều kiện.
The Evil Greebo

3
Nó là nhị phân, không logic. Nó giả định rằng bools là 0 hoặc 1 không đúng trên CLR.
usr

1
xin lỗi, câu trả lời này không thực sự trả lời câu hỏi về toán tử ĐIỀU KIỆN. đây là một chút opperator
Nathan Tregillus

2
Đối với bản ghi, tài liệu được liên kết trong câu trả lời này tuyên bố rõ ràng rằng ^, khi được sử dụng với toán hạng boolean, là một toán tử boolean. "đối với toán hạng bool, toán tử ^ tính kết quả giống như toán tử bất đẳng thức! =". Bạn cũng có thể sử dụng toán hạng số nguyên bitwise-xor ^. C # không phải là C.
15ee8f99-57ff-4f92-890c-b56153

24

Để làm rõ, toán tử ^ hoạt động với cả hai loại tích phân và bool.

Xem MSDN's ^ Operator (C # Reference) :

Toán tử ^ nhị phân được xác định trước cho các kiểu tích phân và bool. Đối với các kiểu tích phân, ^ tính toán OR riêng-OR của các toán hạng của nó. Đối với toán hạng bool, ^ tính toán loại trừ logic-hoặc của các toán hạng của nó; nghĩa là, kết quả là true nếu và chỉ khi chính xác một trong các toán hạng của nó là true.

Có thể tài liệu đã thay đổi kể từ năm 2011 khi câu hỏi này được hỏi.


2
đã được lập trình trong c # trong một thời gian dài, không bao giờ biết điều này! cảm ơn @RichardCL!
Nathan Tregillus

Đây là thông tin tốt nhưng có vẻ thích hợp hơn khi là một nhận xét hoặc chỉnh sửa câu trả lời khác đề cập ^và có trước câu trả lời này khoảng 5 năm. Tôi nghi ngờ bất cứ điều gì đã thay đổi.
Chris

13

Theo yêu cầu của Mark L , Đây là phiên bản chính xác:

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

Đây là bảng sự thật:

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

Tham khảo: Độc quyền HOẶC


2
Câu hỏi được đặt ra là TẠI SAO C # không có toán tử XOR có điều kiện. Điều này không trả lời câu hỏi. Đối với bản thân hàm: hàm này hoạt động dưới dạng XOR có điều kiện - tuy nhiên câu hỏi đặt ra là, nó có hiệu quả hơn XOR không có điều kiện không? Để kiểm tra sự thật độc quyền, XOR phải xác nhận rằng một và chính xác một kết quả là đúng. Điều này có nghĩa là cả hai bên phải được đánh giá và so sánh. Hàm trên kiểm tra cả hai vế của một và điều kiện trong khi đảo ngược một giá trị, ở mức tối thiểu. Nội bộ chúng tôi có biết điều này có gì khác với XOR không?
The Evil Greebo,

6

Ồ vâng, đúng rồi.

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

1
Nó là một toán tử nhị phân, không phải là một toán tử logic. Nó giả định rằng bools là 0 hoặc 1 không đúng trên CLR. Vì vậy, mã này thực sự có thể không hoạt động.
usr

6
@usr, Trong C #, toán tử ^ là logic khi áp dụng cho hai toán hạng Boolean. Bạn đã nhận xét rất nhiều về những câu trả lời này, bạn đã bao giờ chạy bất kỳ đoạn mã nào để kiểm tra giả thuyết của mình chưa?
Marc L.

2
@MarcL. Tôi đã làm: pastebin.com/U7vqpn6G In true, mặc dù true ^ true được cho là false. bool không phải lúc nào cũng bằng 0 hoặc 1. Nó không phải là kiểu logic trên CLR. Nó là một số lượng 8 bit với nội dung tùy ý. Tôi cũng có thể đã tạo IL có thể xác minh để chứng minh vấn đề.
usr

2
Ví dụ: khi sử dụng các ngôn ngữ CLR khác ngoài C #. Tôi nhắc lại: Tôi có thể đã sử dụng ILASM để tạo một assembly an toàn, hoàn toàn có thể xác minh được thực hiện điều này (ở mức IL, giá trị boolean chỉ là một i1, giống như một byte vậy). Đây là hành vi được quản lý an toàn và được xác định 100%. CLR không phải là hoàn thiện; Lần đầu tiên tôi thấy hành vi này là khi sử dụng Microsoft Pex.
usr

1
@EdPlunkett, tôi không nghĩ xe tải của bạn đi cùng tôi. usr cho thấy rằng trong thực tế nó là một toán tử nhị phân . Sự "lạm dụng" mà tôi phàn nàn là cách mà anh ấy đã chứng minh nó, điều mà tôi vẫn duy trì là quá sắc sảo. Nó có thể xảy ra, nhưng đặt việc sử dụng Boolean một cách triệt để vào vùng đất vắng người đến nỗi việc triển khai nó như là CLR-safe sẽ rất nguy hiểm, tệ nhất là lạm dụng (nếu không phải là độc hại) và nên được coi như một lỗi. Những gì chúng tôi chứng minh là bên trong C # giống C hơn chúng ta nghĩ. Liệu mã thực hiện điều này có được coi là hợp lệ hay không là một câu hỏi khác.
Marc L.

4

Xor có điều kiện không tồn tại, nhưng bạn có thể sử dụng logic vì xor được định nghĩa cho boolean và tất cả các phép so sánh có điều kiện đều đánh giá thành boolean.

Vì vậy, bạn có thể nói điều gì đó như:

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

}

Nó là một toán tử nhị phân, không phải là một toán tử logic. Nó giả định rằng bools là 0 hoặc 1 không đúng trên CLR. Vì vậy, mã này thực sự có thể không hoạt động.
usr

@usr ý bạn là gì CLR? Điều này làm việc cho tôi, không chắc chắn nếu tôi bỏ lỡ một trường hợp cạnh đây ...
LunaCodeGirl

3
@Spencevail có thể bạn không nghĩ đến trường hợp boolean không sai có thể không có biểu diễn số nguyên 1. Đây là một thực tế ít được biết đến. Bạn có thể kết thúc trong một tình huống mà xor của hai boolean không sai vẫn không sai! Điều đó nói trong mã cụ thể này, toán tử xor chỉ được áp dụng cho các giá trị trong [0,1] để nhận xét của tôi không áp dụng (hoàn toàn).
usr

1
@Spencevail đó chính xác là trường hợp có thể bị lỗi. Có thể tạo một hàm mã được quản lý an toàn CreateBool (byte) để chuyển một byte thành bool của các bit giống nhau. Khi đó, CreateBool (1) ^ CreateBool (2) là đúng, nhưng CreateBool (1) là đúng và CreateBool (2) cũng đúng! &cũng dễ bị tổn thương.
usr

1
Trên thực tế, tôi vừa báo cáo một lỗi RyuJIT vì họ không xem xét khả năng này và biên dịch &&như thể &đó là một biên dịch sai.
usr

3

Trong khi có toán tử xor logic^ , không có toán tử xor có điều kiện . Bạn có thể đạt được điều kiện xor của hai giá trị A và B bằng cách sử dụng như sau:

A ? (!B) : B

Các parens không cần thiết, nhưng tôi đã thêm chúng để rõ ràng.

Như đã chỉ ra bởi The Evil Greebo, điều này đánh giá cả hai biểu thức, nhưng xor không thể bị đoản mạch như hoặc .


Sự khác biệt giữa logican ^ và điều kiện ^ là gì? oO
Armen Tsirunyan

@Armen Tsirunyan Các toán tử logic thực hiện các phép toán bitwise trong các kiểu hợp lý trong khi các toán tử điều kiện hoạt động trên các giá trị boolean và trả về một kết quả boolean. Xét các giá trị boolean: 0101 ^ 0011có giá trị 0110.
jimreed

3
không, bạn đã hoàn toàn sai lầm. có cả hai loại XOR (chúng được gọi là bitwise và logic, tương ứng) trong C #. Cả hai đều sử dụng ký hiệu ^.
Armen Tsirunyan

1

bạn có thể dùng:

a = b ^ c;

giống như trong c / c ++


0

Không có cái gọi là XOR có điều kiện (đoản mạch). Các toán tử điều kiện chỉ có ý nghĩa khi có một cách để nói rõ ràng kết quả cuối cùng từ việc chỉ xem xét đối số đầu tiên. XOR (và phép cộng) luôn yêu cầu hai đối số, vì vậy không có cách nào để đoản mạch sau đối số đầu tiên.

Nếu bạn biết A = true, thì (A XOR B) =! B.

Nếu bạn biết A = false, thì (A XOR B) = B.

Trong cả hai trường hợp, nếu bạn biết A nhưng không biết B, thì bạn không biết đủ để biết (A XOR B). Bạn phải luôn học giá trị của cả A và B để tính toán câu trả lời. Thực sự không có trường hợp sử dụng nào mà bạn có thể giải quyết XOR mà không có cả hai giá trị.

Hãy nhớ rằng, XOR theo định nghĩa có bốn trường hợp:

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

Một lần nữa, hy vọng điều hiển nhiên ở trên rằng biết giá trị đầu tiên không bao giờ là đủ để có câu trả lời mà không cần biết giá trị thứ hai. Tuy nhiên, trong câu hỏi của bạn, bạn đã bỏ qua trường hợp đầu tiên. Thay vào đó nếu bạn muốn

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

thì bạn thực sự có thể đạt được điều đó bằng một hoạt động có điều kiện đoản mạch:

A && !B

Nhưng đó không phải là XOR.


Tôi không thấy bất kỳ điều gì trong câu trả lời này không có trong ít nhất một câu trả lời ở trên. Tôi không thấy bất kỳ dấu hiệu nào cho thấy chiếc un-xor ngắn mạch của bạn là thứ mà OP đang tìm kiếm, vì anh ấy đã chấp nhận một câu trả lời giả sử rằng anh ấy muốn xor thích hợp.
15ee8f99-57ff-4f92-890c-b56153

Của tôi theo nghĩa đen là câu trả lời duy nhất được đề xuất cho đến nay có thể tạo ra bảng chân lý được yêu cầu của OP mà không cần đánh giá đối số thứ hai.
Kevin Holt

OP cũng hỏi tại sao không có XOR có điều kiện, và trong khi các câu trả lời ở trên nói chính xác rằng đó là vì XOR yêu cầu hai đối số, IMO các câu trả lời trên dường như không giải thích đầy đủ TẠI SAO XOR thực sự cần hai đối số. Rõ ràng là bạn cảm thấy khác, nhưng đối với tôi, rõ ràng là từ các bình luận khác nhau trên trang này rằng hai lập luận cơ bản của XOR vẫn chưa được giải thích đầy đủ cho người mới bắt đầu hoàn chỉnh.
Kevin Holt

1
Bạn đã nói với tôi về nó.
15ee8f99-57ff-4f92-890c-b56153

@Kevin Holt - XOR logic có ý nghĩa nếu bạn cần một trong các điều kiện là đúng nhưng không phải cả hai. Điều đó bạn phải đánh giá cả hai điều kiện không quan trọng. Vấn đề ngắn mạch là một chi tiết cấp thấp mà bạn chỉ phải lo lắng khi xử lý mã quan trọng về hiệu suất (luồng điều khiển chậm). Tôi sẽ quan tâm hơn đến những gì 'độc quyền hoặc' được cho là có nghĩa khi tạo ra một toán tử logic từ nó. Cụ thể, để nó hoạt động giống như phiên bản bitwise (giống như các toán tử khác), hoặc biến nó thành một hoặc độc quyền (bao nhiêu điều kiện bạn muốn, nhưng chỉ một điều kiện có thể đúng).
Thorham

-3

Câu hỏi này đã được trả lời một cách khách quan, nhưng tôi đã gặp phải một tình huống khác. Đúng là không cần XOR có điều kiện. Cũng đúng khi toán tử ^ có thể được sử dụng. Tuy nhiên, nếu bạn chỉ cần kiểm tra trạng thái "true || false" của các toán hạng thì ^ có thể dẫn đến rắc rối. Ví dụ:

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

Trong ví dụ này, nếu trái được đặt thành 10 (0xa) và phải được đặt thành 5 (0x5) thì nhánh "thành công" được nhập. Đối với ví dụ này (đơn giản nếu ngớ ngẩn), điều này sẽ dẫn đến lỗi vì bạn không nên rẽ trái VÀ phải cùng một lúc. Những gì tôi thu thập được từ người hỏi không phải là anh ta thực sự muốn có một điều kiện, mà là một cách đơn giản để thực hiện đúng / sai trên các giá trị được chuyển đến xor.

Một macro có thể thực hiện thủ thuật:

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

Cứ thoải mái tát tôi nếu tôi đi chệch hướng: o)

Tôi đọc câu trả lời của jimreed bên dưới sau khi tôi đăng bài này (Yapdog xấu!) Và của anh ấy thực sự đơn giản hơn. Nó sẽ hoạt động và tôi hoàn toàn không biết tại sao câu trả lời của anh ấy lại bị bỏ phiếu ...


3
Đây là một câu hỏi C #, không phải C / C ++. ifyêu cầu một biểu thức Boolean, nó thậm chí sẽ không biên dịch với một int.
Marc L.
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.