조건식에 비트 연산자를 사용하는 것이 언제 적절한가요?


15

첫째, 일부 배경 : 나는 IT 교사 훈련 중이며 Java의 부울 연산자를 10 학년 클래스에 소개하려고합니다. 선생님이 선생님이 준비한 워크 시트를 살펴보면서 단 하나의 & 또는 | "같은 일을하기"때문에 연산자를 나타냅니다.

&와 &&의 차이점을 알고 있습니다.
&는 "비트 트위들 링"을 수행하기 위해 정수 사이에서 사용하기위한 비트 연산자입니다.
&&는 부울 값 사이에 사용하기위한 조건부 연산자입니다.

이 연산자가 항상 "같은 작업"을하지는 않는다는 점을 증명하기 위해 부울 값 사이에 비트 단위를 사용하면 오류가 발생하는 예를 찾기 시작했습니다. 이 예제를 찾았습니다

boolean bitwise;
boolean conditional;
int i=10, j=12;
bitwise = (i<j) | ((i=3) > 5); // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10; 
conditional = (i<j) || (i=3) > 5 ;  // value of i after oper: 10
System.out.println(conditional+ " "+ i);
i=10; 
bitwise = (i>j) & (i=3) > 5;   // value of i after oper: 3
System.out.println(bitwise+ " "+ i);
i=10; 
conditional = (i>j) && (i=3) > 5;  // value of i after oper: 10
System.out.println(conditional+ " "+ i);

이 예는 식의 후반에 의해 값을 변경해야하는 경우 비트 단위가 열성적인 연산자이고 조건이 단락으로 동작하기 때문에 결과간에 차이가 발생할 수 있음을 보여줍니다 (두 번째는 평가하지 않음) &&의 경우 전반이 거짓이고 ||의 경우에는 참인 경우 반입니다.

이 예제에 문제가 있습니다. 비교하는 것과 동시에 왜 값을 변경하고 싶습니까? 강력한 코딩 방법은 아닙니다. 나는 항상 프로덕션 코드에서 한 줄로 여러 작업을 수행하는 것을 싫어했습니다. 그의 코드의 유지 관리 성과 관련하여 양심이없는 "코딩 카우보이"처럼 보입니다. 일부 도메인에서는 코드가 가능한 한 작아야한다는 것을 알고 있지만 이것이 일반적으로 좋지 않은 방법입니까?

&& 및 ||를 사용하도록 권장하는 선택을 설명 할 수 있습니다. 이상 및 | 이것은 소프트웨어 엔지니어링에서 허용되는 코딩 규칙 이기 때문에 입니다.

그러나 누군가가 조건부 표현에 비트 연산자를 사용하는 더 나은, 심지어 실제적인 예를 줄 수 있습니까?

답변:


16

마스킹 작업을 수행 할 때 적합합니다

if ((a & b)> 0) {...}

여기서 a와 b는 정수입니다

|| 와 | &&와 &는 교환 할 수 없습니다

| & &는 대부분 자체적으로 조건식에 나타나지 않습니다.

편집 : 멘토와 논쟁하지 마십시오. 당신이이기더라도, 당신은집니다. 대신, 같은 수업에서 논리 연산자와 비트 연산자를 혼합하여 학생들을 혼동하고 싶지 않다고 설명하십시오. i = & j는 오류 인 반면 i = 3이고 j = 2이면 i & j = 2 인 경우 설명 할 수 있습니다. 그러나 더 간단한 설명은 부울 (논리) 연산자를 가르치는 것이므로 특수한 비트 단위로 처리하는 것은 수업의 요점에서 산만합니다. 멘토를 "잘못"만들 필요는 없으며, 반대 사례를 만들 필요도 없습니다. 수업의 초점은 부울 연산자가 아니라 비트 연산자가 .

결과적으로 비트 연산자를 가르치기 시작할 때 + 및-가 & 및 |와 동일한 결과를 생성하는 특별한 경우를 보여줄 필요가 없습니다.


위의 코드는 틀리지 않지만 혼란 스러울 수 있지만 코드에 오류가 없다는 것을 의미합니까? 이 방법으로 비트 연산자를 사용하는 것은 읽기 쉽지 않으므로 코드 검토에서 보았을 때 마음에 들지 않지만 Java (및 C #도 System.out.println을 무시)입니다.
Steve

@Steven A. Lowe에 답변 해 주셔서 감사합니다. 당신은 말했다 "|| 및 |와 && 및 교환 할 수 없습니다"하지만, bitwise = !(true & true == false);그리고 condition = !(true && true == false);모두가 상호 교환이 경우에는 너무 true로 평가합니다? 코드는 여전히 컴파일되기 때문에 구문 상으로 가능합니다. 나는 단락 2에서 언급했듯이 그것들이 의미 상 다른 것들에 사용된다는 것에 동의합니다. & "거의 그 자체로는 조건부로 나타나지 않습니다". 나는 이러한 "거의 절대"사례를 찾고 있으며, 그것이 합법적으로 존재하는지 궁금합니다.
Deerasha

@Deerasha : || &&는 부울 에서만 작동 합니다. & 및 | 정수 부울 에서 작동 -비트 연산자 ( 여러 비트 에서 작동하도록 의도 됨 )를 사용하여 부울을 조작 점은 거의 없으며 , 포기를 사용하여 혼동하면 코드가 혼동되고 예기치 않은 동작이 발생할 수 있습니다 (예 : 실수로 정수 대신 정수를 사용하는 경우) 부울의 비트 연산자)는 불평하지 않을 것이다
스티븐 A. 로우에게

예 @Steve Haigh, 컴파일러는 그것을 거부하지 않지만, 내가 링크 된 공개 코딩 표준으로 판단하여 올바른 사용 방법은 아닙니다. 코딩 표준을 준수하지 않기 때문에 편안하게 해제 할 수 있습니까? 아니면 Java가 이것이 부적절한 사용임을 나타낼 수 있습니까?
Deerasha

2
@Steven A. Lowe : i = 3이고 j = 2이면 i & j = 2이고 i && j는 오류 입니다. 훌륭합니다! 간단하고 요점을 지적합니다. 10 학년 레벨에서는 여전히 부울 형식과 연산자가 적용 할 대상에 익숙해지기 때문에 실수를 저지를 가능성이 높습니다. 정말 고맙습니다! 내 멘토와 논쟁하지 않는 것에 대한 훌륭한 조언.
Deerasha

12

비 비트 연산자 &&||단락 회로 운영된다. 다시 말해 &&LHS가 거짓이면 RHS는 평가되지 않습니다. 로 ||좌변에 해당하는 경우, 다음 RHS는 평가되지 않습니다. 한편, 비트 연산자 &|비 단락 회로, 그리고 항상 LHS와 RHS 모두 평가합니다. 그렇지 않으면 그것들은if 성명서 합니다.

비 단락 연산자를 사용할 때 가치를 볼 수있는 유일한 시간은 RHS에 모든 경우에 원하는 부작용이 있는지 여부입니다. 나는 당신이 이것을 원할 구체적인 예를 생각할 수 없으며, 그것이 좋은 습관이라고 믿지 않지만 그 차이입니다.


1
+1. 정확히 말하면, 부울을 비교할 때 비트 연산자와 논리 연산자는 항상 동일한 결과를 반환하지만 (적어도 Java와 C #에서는) 논리 연산자 만 단락됩니다.
Steve

답변 주셔서 감사합니다. 귀하의 단락 1은 조건부가 단락으로 작동하는 동안 비트 단위는 열망하는 연산자 라고 진술하여 단락 4에서 얻으려고했습니다 . 귀하의 2 항은 5 항에서 설명한 문제입니다. 차이점을 알고 있지만 귀하와 제가 생각할 수없는 구체적인 예를 찾고 있습니다.
Deerasha

7

일반적인 철학적 대답은 부울 연산자에 비트 연산자를 사용하는 것이 비정형적이고 코드를 읽기 어렵게한다는 것입니다. 실제로 (제작중인 코드의 경우) 더 읽기 쉬운 코드를 유지 관리하기가 더 쉬워지고 더 바람직합니다.

단락 작업자의 실제 사용을 위해서는 다음과 같은 경우를 참조하십시오.

if (args.length > 0 && args[0] == 'test') ....

if (b != NULL && b.some_function()) ...

if (b == NULL || b.some_function()) ...

이러한 유형의 작업은 실제 코드에서 자주 나타납니다.


티파. 15 살짜리 어린이들에게 1 &이 2보다 "읽기가 더 어렵다"고 어떻게 설명 합니까? 부울 피연산자에 대해 두 연산자가 같은 방식으로 작동하지 않는 예는 없습니다. 더 읽기 쉽고 코드를 쉽게 유지 관리 할 수 ​​있다는 점에 동의합니다. 나는 그들이 아름다운 코드를 작성하도록 격려하고 싶다. 그러나 도구 모음에 증거가 있으면“내가 그렇게 말했기 때문에”보다 더 설득력이 있습니다. 나는 그것을 그 링크에서 표준으로 언급했으며, 내가 찾고있는 예를 얻지 못하면 그에 의존해야 할 수도 있습니다. @Steve Haigh에게 물었을 때 : java는 이것을 부적절한 사용으로 표시해야합니까?
Deerasha

@ Deerasha 나는 당신의 멘토와 더 많은 논쟁을 생각하고있었습니다. 수업을 위해 논리 조건에 비트 연산자를 사용할 수 있다고 말하지 마십시오.
Kathy Van Stone

4

비트 마스크 열거를 비교하는 경우 비트 연산자를 사용합니다. 예를 들어, 상태 열거와 그 상태 중 둘 이상에있을 수있는 객체가 있습니다. 이 경우 비트 단위로 수행하거나 객체에 둘 이상의 상태를 할당합니다.

예를 들어, state = CONNECTED | IN_PROGRESS여기서, CONNECTED could be 0x00000001IN_PROGRESS 0x00000010

자세한 내용은 플래그 열거 형 설명서를 참조하십시오.


덕분에 나는 전에 알지 못했던 비트 연산자의 응용 프로그램을 배웠습니다! 그러나이 예제에서는 비트 연산자 적용됩니다. 조건부 대신 비트 단위를 사용하면 컴파일이 발생하지만 출력이 잘못되는 잘 작성된 코드를 찾고 있습니다. 즉, 그러한 코드 스 니펫이 존재하는 경우입니다.
Deerasha

Java를 호출 할 때 이것이 Java에서 발생할 수 있다고 생각하지 않습니다. 비트 단위 및 / 또는 논리 할 수없는 값에 대한 연산자 또는 &. 이것이 Java의 경우인지는 기억 나지 않지만, C # MSDN에 있다는 것을 알고 있습니다. "이진 연산자는 정수 유형과 부울에 대해 미리 정의되어 있습니다. 정수 유형의 경우 피연산자의 비트 OR을 계산합니다. bool operands | 피연산자의 논리 OR을 계산합니다 "
pwny

더 많은 연구를 한 결과, | 그리고 || Java의 부울 피연산자에 대한 & 및 &&는 단락 동작 이므로 설명하는 시나리오는 실제로 불가능합니다.
pwny

0

잘못의 간단한 예 :

int condA=1, condB=2;

if (condA!=0 && condB!=0) {
    // correct!
}
if ((condA & condB)!=0) {
    // never executed
}

여기에는 두 가지 조건이 있으며 둘 다 0이 아닙니다. 그러나 비트 단위의 &결과는 0입니다.


@Javier : 답변 해 주셔서 감사합니다. 조금 혼란 스럽습니다. Java로 작업 중이며이 코드는 컴파일되지 않습니다. (condA && condB)&&는 2 int초 동안 작동하지 않고 2 개의 부울 만 작동하므로 오류가 발생 합니다. (condA & condB)올바른 반면, int 자바로 평가 if(int)하면 오류도 말할 수 없습니다 . 당신은 내가 찾고있는 것을 이해하는 첫 번째 사람입니다-정확히 그 예가 잘못 입니다.
Deerasha

오랫동안 자바를 사용하지 않은 ... 시도 (Boolean(condA) && Boolean(condB)) (내가 생각 Boolean(x)이다 true권리, 비 - 제로 정수에 대해?)
하비에르

아니요 @Javier : int에서 boolean으로 캐스트 할 수 없습니다.
Deerasha

무엇에 대해 ((condA!=0) && (condB!=0))?
Javier

@Javier yay는 컴파일되지만 "잘못"은 더 이상 설명되어 있지 않으므로 if (((condA!=0) && (condB!=0))) { System.out.println("correct"); } if (((condA!=0) & (condB!=0))) { System.out.println("never executed?"); }두 print 문을 모두 실행합니다.
Deerasha
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.