조건부 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.