조건부 XOR?


87

C #에 조건부 XOR연산자 가없는 이유는 무엇입니까?

예:

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

15
!=대체로 어떻게 작동합니까?
— Pascal Cuoq 2011-06-28

45
C # 에는 xor 연산자 (x ^ y)가 있습니다. 그러므로 나는 질문의 전제를 부인합니다. C #에 xor 연산자가 없다고 믿는 이유를 설명해 주시겠습니까? 사람들이 C #에 대해 잘못된 것을 믿는 이유를 알고 싶습니다.
— Eric Lippert 2011-06-28

3
@Eric Lippert : 그는 논리 연산자 ( & | ^)와 조건 연산자 ( && ||)를 언급하고 있다고 생각 합니다. 하지만 당신 말이 맞습니다. (물론) 논리적 XOR이 있습니다 ...
— BoltClock

14
@BoltClock : 오, 만약 질문이 "왜 단락 xor 연산자가 없습니까?" -어떻게있을 수 있습니까? "and"로 첫 번째 인수가 거짓이면 두 번째 인수를 평가할 필요가 없습니다. "or"를 사용하면 첫 번째 인수가 참이면 두 번째 인수를 평가할 필요가 없습니다. xor에 대해 항상 두 인수를 모두 평가해야하므로 단락이 발생하지 않습니다.
— Eric Lippert

4
질문 자체는 Microsoft에 더 적합한 질문입니다. 따라서 반대 투표를해야하는 적절한 이유입니다.하지만 ^ 연산자 때문에 반대 투표를 한 사람이 있다면 더 자세히 읽어야합니다. 단순히 "XOR이없는 이유"가 아니라 논리적입니다.
— The Evil Greebo 2011-06-28

답변:


121

C #에서 조건부 연산자는 필요한 경우 에만 보조 피연산자를 실행 합니다 .

XOR 은 정의에 따라 두 값을 모두 테스트 해야 하므로 조건부 버전은 어리석은 것입니다.

예 :

  • 논리적 AND : &-매번 양쪽을 테스트합니다.

  • 논리적 OR : |-매번 양쪽을 테스트합니다.

  • 조건부 AND : &&-첫 번째면이 참인 경우 두 번째 면만 테스트합니다.

  • 조건부 OR : ||-첫 번째면이 거짓이면 두 번째 면만 테스트합니다.


35
XOR 연산자는 "조건부 연산자는 필요한 경우에만 보조 피연산자를 실행"규칙을 위반하지 않습니다. 항상 필요할 것입니다.
— Nathan Kovner

2
조건부 XOR은 특정 패턴에 대한 멋지고 우아한 지름길이 될 수 있지만, 언어에 포함 할 수있을만큼 정당한지는 확실하지 않습니다. XOR이 유용 할 수있는 패턴의 예는 조건부 부정입니다. 두 번째 부울식이 주어 졌을 때 부울식이 부정되어야하는 경우입니다.
— SalvadorGomez

1
한동안 이것에 응답하지 않았지만 @KhyadHalda의 인기있는 댓글에 응답하기 위해 : 왜 절대 사용되지 않을 것이라는 것을 알고있는 것을 만들었 을까요? 당신은 의도적으로 죽은 코드를 작성하고있을 것입니다.
— The Evil Greebo

조건부 XOR 연산자가 사용자가 정의한 규칙 (Khyad의 의견)을 위반하지 않고 실제로 어떤 경우에 유용 할 것이라는 사실을 감안할 때 이러한 연산자가 존재하는 "silliness"를 거의 무효화합니다.
— Syndog

1
조건부 XOR이 어떻게 유용할까요? 조건부 XOR은 양쪽이 같거나 같지 않은지 확인하기 위해 양쪽을 비교하지 않고는 평가할 수 없습니다. 두 개의 bool을 비교하는 조건부 XOR의 개념조차도 여전히 각 bool의 값을 확인하고 동등성을 테스트해야합니다.
— The Evil Greebo

280

질문이 조금 구식이지만 ...

이 연산자가 작동하는 방식은 다음과 같습니다.

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

다음은! = 연산자가 bool 유형에서 작동하는 방식입니다.

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

보시다시피 ^^존재하지 않는 것은 기존의!=


46
이것은 실제로 질문을 직접적이고 정확하게 해결하는 유일한 대답입니다.
— usr

39
나는 여기에 앉아 있고 내가 !=이것을 위해 일할 것이라는 것을 깨닫지 못했다 .
— AdamMc331 2015-08-19

1
답은 맞지만 댓글은 그렇지 않습니다. "C #에 조건부 XOR이없는 이유는 무엇입니까?"라는 질문은 다루지 않습니다. 엄밀히 말하면 이것은 논리 연산자가 아니라 관계형 같음 연산자입니다. 결과는 XOR과 동일하지만 다른 클래스에 있습니다. 두 개의 부울 값을 테스트 할 때만 XOR과 비교되며 연산자의 양쪽을 모두 평가해야합니다.
— The Evil Greebo

3
@TheEvilGreebo-당신의 말은 사실입니다. ! = 연산자는 기술적으로 조건부 XOR 연산자가 아닙니다. 그러나이 답변은 "! = 연산자가 있기 때문에 조건부 XOR 연산자는 존재하지 않습니다."라고 효과적으로 말합니다. 어쨌든 그렇게 읽었습니다.
— Syndog

6
나는 거의 모든 사람들이 실제로 Booleans에 XOR을 작성하기를 원했다고 생각합니다. 같은 논리가 AND하고 OR있지만, 같은 아무것도 XOR. 또는 적어도 우리는 몰랐어요 !=:) @TheEvilGreebo
— M.kazem Akhgary

30

논리 XOR 연산자가 있습니다. ^

문서 : C # 연산자 및 ^ 연산자


2
조건이 아닌 논리적입니다. 논리 및 = &, 조건부 및 = &&. 그는 조건부에 대해 묻고 있습니다.
— The Evil Greebo 2011-06-28

3
논리적이지 않고 바이너리입니다. bools는 CLR에서 true가 아닌 0 또는 1이라고 가정합니다.
— usr

1
죄송합니다.이 답변은 실제로 CONDITIONAL 연산자에 대한 질문에 대한 답변이 아닙니다. 이 비트 opperator입니다
— 나단 Tregillus

2
레코드의 경우이 답변에 링크 된 문서 ^는 부울 피연산자와 함께 사용할 때 부울 연산자 라고 명시 적으로 명시 합니다. "부울 피연산자의 경우 ^ 연산자는 부등식 연산자! ="와 동일한 결과를 계산합니다. 를 사용하여 비트 xor 정수 피연산자를 사용할 수도 있습니다 ^. C #은 C가 아닙니다.
— 15ee8f99-57ff-4f92-890c-b56153

24

설명처럼 ^ 연산자는 정수 유형과 부울 모두에서 작동합니다.

참조 MSDN의 ^ 연산자 (C # 참조) :

이진 ^ 연산자는 정수 유형 및 부울에 대해 사전 정의됩니다. 정수 유형의 경우 ^는 피연산자의 비트 배타적 OR을 계산합니다. bool 피연산자의 경우 ^는 피연산자의 논리적 배타적 또는 논리 연산을 계산합니다. 즉, 피연산자 중 정확히 하나가 참인 경우에만 결과가 참입니다.

이 질문이 제기 된 2011 년 이후로 문서가 변경되었을 수 있습니다.


2
오랫동안 C #으로 프로그래밍을 해왔지만 결코 알지 못했습니다! 감사합니다 @RichardCL!
— Nathan Tregillus

이것은 좋은 정보이지만 ^이것을 언급 하고 5 년 앞선 다른 답변에 대한 의견이나 편집으로 더 적절 해 보입니다 . 나는 아무것도 바뀌지 않았다고 의심한다.
— Chris

13

Mark L의 질문에 따라 올바른 버전은 다음과 같습니다.

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

다음은 진리표입니다.

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

참조 : 독점 OR


2
질문은 C #에 조건부 XOR 연산자가없는 이유입니다. 이것은 질문에 대한 답이 아닙니다. 함수 자체에 관해서 :이 함수는 조건부 XOR로 작동하지만 질문은 비 조건부 XOR보다 더 효율적입니까? 배타적 진실을 테스트하기 위해 XOR은 정확히 하나의 결과가 참인지 확인해야합니다. 이는 양쪽 모두를 평가하고 비교해야 함을 의미합니다. 위의 함수는 최소한 하나의 값을 반전시키면서 및 조건의 양쪽을 테스트합니다. 이것이 XOR과 다른지 내부적으로 알고 있습니까?
— The Evil Greebo

6

네, 그렇습니다.

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

1
논리 연산자가 아니라 이항 연산자입니다. bools는 CLR에서 true가 아닌 0 또는 1이라고 가정합니다. 따라서이 코드는 실제로 작동하지 않을 수 있습니다.
— usr

6
@usr, C #에서 ^ 연산자는 두 개의 부울 피연산자에 적용될 때 논리적입니다. 이 답변을 통해 끔찍한 댓글을 달았습니다. 가설을 테스트하기 위해 코드를 실행 한 적이 있습니까?
— Marc L.

2
@MarcL. 나는했다 : pastebin.com/U7vqpn6G 참 ^ 참이 거짓이어야하지만 참을 인쇄합니다. 부울은 하지 그것은 CLR에 논리적 인 유형이 아닌 항상 0 또는 1과 동일. 임의의 내용을 가진 8 비트 수량입니다. 문제를 설명하기 위해 검증 가능한 IL을 생성 할 수도 있습니다.
— usr

2
예를 들어 C # 이외의 다른 CLR 언어를 사용하는 경우. 반복합니다 : ILASM을 사용하여 완전히 검증 가능하고 안전한 어셈블리를 만들 수있었습니다 (IL 수준에서 부울 값은 i1바이트와 ​​마찬가지로). 이것은 100 % 정의되고 안전하게 관리되는 행동입니다. CLR은 대략적인 것이 아닙니다.; 이 동작을 처음 본 것은 Microsoft Pex를 사용할 때였습니다.
— usr

1
@EdPlunkett, 나는 당신의 트럭이 나와 함께 있다고 생각하지 않습니다. usr은 내부적으로 그것이 실제로 이항 연산자 임을 보여주었습니다 . 내가 불평 한 "남용"은 그가 그것을 증명 한 수단이었고, 내가 여전히 너무 첨예하다고 주장한다. 그것은 일어날 수 있지만, CLR 안전으로 배포하는 것은 기껏해야 위험하고 최악의 경우 악의적이며 (악의적이지 않은 경우) 버그로 취급되어야 할 정도로 부울을 무인의 땅에 철저히 사용합니다. usr이 증명하는 것은 내부적으로 C #이 우리 둘 다 생각했던 것보다 더 C와 비슷하다는 것입니다. 이를 수행하는 코드가 유효한지 여부는 또 다른 질문입니다.
— Marc L.

4

조건부 xor는 존재하지 않지만 xor가 부울에 대해 정의되고 모든 조건부 비교가 부울로 평가되므로 논리 xor를 사용할 수 있습니다.

따라서 다음과 같이 말할 수 있습니다.

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

}

논리 연산자가 아니라 이항 연산자입니다. bools는 CLR에서 true가 아닌 0 또는 1이라고 가정합니다. 따라서이 코드는 실제로 작동하지 않을 수 있습니다.
— usr

@usr CLR은 무엇을 의미합니까? 내가 ... 여기 가장자리 케이스를 놓친 경우에 확실하지, 나를 위해 일한
— LunaCodeGirl

3
@Spencevail 아마도 거짓이 아닌 부울이 정수 표현을 갖지 않을 수 있다는 경우에 대해 생각하지 않았을 것입니다 1. 이것은 약간 알려진 사실입니다. 두 개의 거짓이 아닌 부울의 xor가 여전히 거짓이 아닌 상황에서 끝날 수 있습니다! 즉,이 특정 코드에서 xor 연산자는 [0,1]의 값에만 적용되므로 내 의견이 (완전히) 적용되지 않습니다.
— usr

1
@Spencevail은 정확히 실패 할 수있는 경우입니다. 바이트를 동일한 비트의 부울로 변환하는 안전한 관리 코드 함수 CreateBool (byte)를 만들 수 있습니다. 그러면 CreateBool (1) ^ CreateBool (2)가 true이지만 CreateBool (1)이 true이고 CreateBool (2)도 true입니다! &또한 취약합니다.
— usr

1
사실 저는 RyuJIT 버그를보고했습니다. 그들이이 가능성을 고려하지 않고 잘못 컴파일 된 &&것처럼 컴파일했기 때문 &입니다.
— usr

3

논리 xor 연산자 가있는 동안^ 더 없다 조건부 xor 연산자 . 다음을 사용하여 두 값 A와 B의 조건부 xor를 얻을 수 있습니다.

A ? (!B) : B

괄호는 필요하지 않지만 명확성을 위해 추가했습니다.

The Evil Greebo가 지적한 것처럼 이것은 두 표현을 모두 평가하지만 xor는 and and or 처럼 단락 될 수 없습니다 .


논리 ^와 조건 ^의 차이점은 무엇입니까? oO
— Armen Tsirunyan 2011-06-28

@Armen Tsirunyan 논리 연산자는 조건부 연산자가 부울 값에 대해 작동하고 부울 결과를 반환하는 동안 의미있는 유형에서 비트 연산을 수행합니다. 부울 값 고려 : 0101 ^ 0011has the value 0110.
— jimreed

3
아니, 당신은 완전히 틀 렸습니다. C #에는 두 가지 유형의 XOR (각각 비트 및 논리라고 함)이 있습니다. 둘 다 ^ 기호를 사용합니다.
— Armen Tsirunyan 2011-06-28

1

당신이 사용할 수있는:

a = b ^ c;

C / C ++ 에서처럼


0

조건부 (단락) XOR과 같은 것은 없습니다. 조건부 연산자는 첫 번째 인수 만보고 최종 결과를 확실히 알 수있는 방법이있을 때만 의미가 있습니다. XOR (및 덧셈)에는 항상 두 개의 인수가 필요하므로 첫 번째 인수 후에 단락 할 방법이 없습니다.

A = true를 안다면 (A XOR B) =! B입니다.

A = false를 안다면 (A XOR B) = B입니다.

두 경우 모두 A는 알지만 B는 알지 못한다면 충분히 알지 못합니다 (A XOR B). 답을 계산하려면 항상 A와 B의 값을 모두 배워야합니다. 두 값없이 XOR을 해결할 수있는 사용 사례는 말 그대로 없습니다.

XOR은 정의에 따라 네 가지 경우가 있습니다.

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

다시 말하지만, 위의 내용에서 첫 번째 값을 아는 것만으로는 두 번째 값을 알지 않고는 답을 얻을 수 없다는 것이 분명합니다. 그러나 귀하의 질문에서 첫 번째 경우를 생략했습니다. 대신 원한다면

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

그런 다음 단락 조건부 작업을 통해 실제로 얻을 수 있습니다.

A && !B

그러나 그것은 XOR이 아닙니다.


이 답변에서 위의 답변 중 하나 이상에 포함되지 않은 것은 없습니다. 그가 적절한 xor를 원한다고 가정하는 대답을 수락했기 때문에 단락 가능한 un-xor가 OP가 찾고 있던 것임을 나타내는 표시가 없습니다.
— 15ee8f99-57ff-4f92-890c-b56153

내 것은 말 그대로 두 번째 인수를 평가하지 않고 OP의 요청 된 진리표를 생성 할 수있는 지금까지 제안 된 유일한 대답입니다.
— Kevin Holt

또한 OP는 조건부 XOR이없는 이유를 물었고 위의 답변은 XOR에 두 개의 인수가 필요하기 때문이라고 올바르게 말하지만 IMO 위의 답변은 XOR에 실제로 두 개의 인수가 필요한 이유를 충분히 설명하지 않은 것 같습니다. 분명히 당신은 그렇지 않다고 느끼지만,이 페이지의 다양한 의견을 통해 XOR의 기본적인 두 가지 주장이 아직 완전한 초보자에게 완전히 설명되지 않았다는 것이 분명했습니다.
— Kevin Holt

1
당신이 그것에 대해 말 했어요.
— 15ee8f99-57ff-4f92-890c-b56153

@Kevin Holt-논리 XOR은 조건 중 하나가 참이어야하지만 둘 다가 아닌 경우에 의미가 있습니다. 두 조건을 모두 평가해야한다는 것은 중요하지 않습니다. 단락 문제는 성능이 중요한 코드를 처리 할 때만 걱정해야하는 낮은 수준의 세부 사항입니다 (제어 흐름이 느림). 논리 연산자를 만들 때 '배타적 또는'가 의미하는 바에 더 관심이 있습니다. 즉, 비트 버전 (다른 연산자처럼)처럼 작동하거나 또는 배타적으로 만들거나 (원하는만큼 많은 조건이 있지만 하나만 참일 수 있습니다).
— Thorham

-3

이 질문은 정서적으로 답변되었지만 다른 상황에 직면했습니다. 조건부 XOR이 필요 없다는 것은 사실입니다. ^ 연산자를 사용할 수 있다는 것도 사실입니다. 그러나 피연산자의 "true || false"상태 만 테스트해야하는 경우 ^가 문제를 일으킬 수 있습니다. 예를 들면 :

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

이 예에서 left가 10 (0xa)으로 설정되고 right가 5 (0x5)로 설정되면 "success"분기가 입력됩니다. 이 (어리 석다면 단순한) 예제의 경우, 동시에 좌회전과 우회전을해서는 안되므로 버그가 발생합니다. 질문자로부터 얻은 것은 그가 실제로 조건부를 원했다는 것이 아니라 xor에 전달 된 값에 대해 참 / 거짓을 수행하는 간단한 방법입니다.

매크로는 트릭을 수행 할 수 있습니다.

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

내가 틀렸다면 자유롭게 때려 눕히십시오 : o)

나는 이것을 게시 한 후 아래 jimreed의 답변을 읽었으며 (나쁜 Yapdog!) 실제로 더 간단합니다. 그것은 효과가있을 것이고 나는 그의 대답이 왜 거절되었는지 전혀 모른다 ...


3
이것은 C / C ++가 아닌 C # 질문입니다. if부울 표현식이 필요하며 int로 컴파일되지도 않습니다.
— Marc L.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.