&연산자가 | 연산자보다 우선순위가 높은 이유?

_의 이미지

C언어를 보면, 연산자 우선순위가

&
^
|
&&
||

이렇습니다. 저는 조그만 언어를 설계하고 있는데, 우선순위를 C처럼 복잡하지 않고 간단하게 하려 합니다.
전공자가 아닌지라 이산수학 같은걸 배우지 않아서 잘 모르겠습니다. 원래 and가 or 보다 우선순위가 높은게 수학적으로 더 논리적이고 프로그래밍 할때 더 어울리는 건지 궁금합니다.

익명 사용자의 이미지

그거는 쉽게 생각해보면 답이 나올것 같습니다.
앤드라면 우선 조건에서 둘다 만족해야 하기 때문에 무조건 조건을 모두 검사하게 됩니다.
하지만 오어라면 앞에 조건이 틀릴경우에만 뒤에 조건을 검사하기때문에
앤드가 더 우선순위가 높은게 맞겠지요.

myueho의 이미지

Anonymous wrote:

앤드라면 우선 조건에서 둘다 만족해야 하기 때문에 무조건 조건을 모두 검사하게 됩니다.

틀립니다.
and의 경우 왼항이 false면 오른항을 계산하지 않습니다.

totohero의 이미지

myueho wrote:
Anonymous wrote:

앤드라면 우선 조건에서 둘다 만족해야 하기 때문에 무조건 조건을 모두 검사하게 됩니다.

틀립니다.
and의 경우 왼항이 false면 오른항을 계산하지 않습니다.


아무튼 위 두분의 이야기는 &와 |의 연산자 우선 순위가 왜 그렇게 되었는지와는 무관하다고 봅니다. 자신이 나타내고자 하는 논리표현이 정해져있는 이상 연산자 우선 순위에 따라 달라지는 건 괄호의 갯수 뿐이겠지요.

제 생각엔, *가 +보다 우선 순위가 높은 이유도 그렇고 일반적으로 많이 쓰는 논리식의 형태가 우선 순위에 영향을 미친게 아닌가 싶습니다.

공학에서 (a+b)*(c+d)의 연산보다는 a*b + c*d + ... 의 연산을 통계적으로 더 많이 쓰지 않나싶네요. 특히 신호처리를 할때... (DSP의 MAC instruction이 존재하는 이유도 그렇지 않나요?)

느낌인지는 몰라도 일반적으로 코딩을 하다가도 보면 a && b || c && d 와 같은 식을 써야 하는 경우가 (a || b) && (c || d) 와 같은 경우보다 많았던 것 같습니다.

아무래도 인생은 세부적으로는 && 연산자처럼 이것저것 조건을 맞춰도 크게는 ||연산자처럼 유들유들하게 살아야하지 않을까 싶기도 합니다 ^^

vacancy의 이미지

and 는 흔히 product 로, or 는 흔히 sum 으로 표현하죠.
( T = 1, F = 0 으로 놓고 진리표를 만들어보면 대강 비슷하니까요. )

그렇다면 우리가 product를 sum보다 위의 우선순위로 놓는 이유와
거의 같지 않을까요. :roll:

lifthrasiir의 이미지

사실 연산자 우선순위는 만들기 나름이긴 한데 vacancy 님 말씀처럼 논리곱/논리합이라는 용어 자체에서 순서가 결정된 게 아닌가 싶습니다. ;;; 정확한 자료가 있을 지 모르겠네요.

- 토끼군

jongwooh의 이미지

myueho wrote:

틀립니다.
and의 경우 왼항이 false면 오른항을 계산하지 않습니다.

컴파일러 최적화에서 그렇게 하지요. &연산에서는 몇항이 나타나더라도 계산중에 한 항만 false가 나타나도 나머지 항의 계산을 모두 건너뛰고 전체 수식을 false로 처리해 버립니다. | 연산에서는 계산하다가 한 항이라도 true가 나오면 나머지 항을 모두 생략하고 lvalue 에 true를 대입합니다.

똑똑한 컴파일러일수록 최적화때문에 문제가 생기는 경우가 있지요. 계산을 생략한 항이 변수가 아니라 함수이고, side effect를 가지도록 코딩되어 있을때 (즉 비교하면서 메모리를 바꿀때) 해야 할걸 안해버리기 때문에 버그가 되는 경우가 있을 수 있습니다.

you must know the power of dark side.

익명 사용자의 이미지

논리학에서는 or < and < not(negation) 이런식으로 연산 우선순위를 설정하고 있습니다. 보통의 프로그래밍 랭귀지들은 이를 그대로 따르고 있으니 당연히 연산 우선순위가 저와 같이 되겠죠. 그런데 왜 저렇게 하느냐라고 묻는다면 그냥 "약속"이라고 얘기할 수 밖에 없겠네요.

totohero의 이미지

jwhan wrote:
myueho wrote:

틀립니다.
and의 경우 왼항이 false면 오른항을 계산하지 않습니다.

컴파일러 최적화에서 그렇게 하지요. &연산에서는 몇항이 나타나더라도 계산중에 한 항만 false가 나타나도 나머지 항의 계산을 모두 건너뛰고 전체 수식을 false로 처리해 버립니다. | 연산에서는 계산하다가 한 항이라도 true가 나오면 나머지 항을 모두 생략하고 lvalue 에 true를 대입합니다.

똑똑한 컴파일러일수록 최적화때문에 문제가 생기는 경우가 있지요. 계산을 생략한 항이 변수가 아니라 함수이고, side effect를 가지도록 코딩되어 있을때 (즉 비교하면서 메모리를 바꿀때) 해야 할걸 안해버리기 때문에 버그가 되는 경우가 있을 수 있습니다.


그러나 적어도 C 언어에서는 (경우에 따라 오른쪽 항의 evaluation을 생략하는 것이) 컴파일러 최적화와 같은 옵션이 아니라 표준에 정의된 필수 사항입니다. 그 경우 오른쪽항의 evaluation이 side effect를 가지도록 코딩하는 것 자체가 버그입니다.
line7979의 이미지

tomoyo wrote:
C언어를 보면, 연산자 우선순위가

&
^
|
&&
||

전 '^'(XOR)연산자가 '&'와 '|'사이에 있는지 그게 참 궁금합니다

종종 자신을 돌아보아요!~

하루 1% 릴리즈~~

tinywolf의 이미지

totohero wrote:
jwhan wrote:
myueho wrote:

틀립니다.
and의 경우 왼항이 false면 오른항을 계산하지 않습니다.

컴파일러 최적화에서 그렇게 하지요. &연산에서는 몇항이 나타나더라도 계산중에 한 항만 false가 나타나도 나머지 항의 계산을 모두 건너뛰고 전체 수식을 false로 처리해 버립니다. | 연산에서는 계산하다가 한 항이라도 true가 나오면 나머지 항을 모두 생략하고 lvalue 에 true를 대입합니다.

똑똑한 컴파일러일수록 최적화때문에 문제가 생기는 경우가 있지요. 계산을 생략한 항이 변수가 아니라 함수이고, side effect를 가지도록 코딩되어 있을때 (즉 비교하면서 메모리를 바꿀때) 해야 할걸 안해버리기 때문에 버그가 되는 경우가 있을 수 있습니다.


그러나 적어도 C 언어에서는 (경우에 따라 오른쪽 항의 evaluation을 생략하는 것이) 컴파일러 최적화와 같은 옵션이 아니라 표준에 정의된 필수 사항입니다. 그 경우 오른쪽항의 evaluation이 side effect를 가지도록 코딩하는 것 자체가 버그입니다.

저도 잘 써먹고 있는 걸요..
if (p != NULL && p->pop()) return true;
이런 식으로.. ㅎㅎ

ㅡ_ㅡ;

totohero의 이미지

line7979 wrote:
tomoyo wrote:
C언어를 보면, 연산자 우선순위가

&
^
|
&&
||

전 '^'(XOR)연산자가 '&'와 '|'사이에 있는지 그게 참 궁금합니다


임의의 a, b에 대해 a & b가 true(?)일 확률, a ^ b가 true일 확률, a | b가 true일 확률이 점점 커진다는 원칙 정도는 있군요.
happycat의 이미지

tinywolf wrote:
totohero wrote:
jwhan wrote:
myueho wrote:

틀립니다.
and의 경우 왼항이 false면 오른항을 계산하지 않습니다.

컴파일러 최적화에서 그렇게 하지요. &연산에서는 몇항이 나타나더라도 계산중에 한 항만 false가 나타나도 나머지 항의 계산을 모두 건너뛰고 전체 수식을 false로 처리해 버립니다. | 연산에서는 계산하다가 한 항이라도 true가 나오면 나머지 항을 모두 생략하고 lvalue 에 true를 대입합니다.

똑똑한 컴파일러일수록 최적화때문에 문제가 생기는 경우가 있지요. 계산을 생략한 항이 변수가 아니라 함수이고, side effect를 가지도록 코딩되어 있을때 (즉 비교하면서 메모리를 바꿀때) 해야 할걸 안해버리기 때문에 버그가 되는 경우가 있을 수 있습니다.


그러나 적어도 C 언어에서는 (경우에 따라 오른쪽 항의 evaluation을 생략하는 것이) 컴파일러 최적화와 같은 옵션이 아니라 표준에 정의된 필수 사항입니다. 그 경우 오른쪽항의 evaluation이 side effect를 가지도록 코딩하는 것 자체가 버그입니다.

저도 잘 써먹고 있는 걸요..
if (p != NULL && p->pop()) return true;
이런 식으로.. ㅎㅎ

말씀하신 것 들은 short circuit 또는 Minimal evaluation이라 불리는 evaluation strategy 입니다.

아래 자료를 참고하세요.

http://en.wikipedia.org/wiki/Lazy_evaluation#Minimal_evaluation

creativeidler의 이미지

XOR은 많은 경우에 OR을 대체해서 쓰이기도 하고 OR과 동작이 비슷하기 때문에 AND보다 낮은 것은 자연스러운 것 같습니다. 하지만 XOR이 OR보다 앞서는 이유는 잘 모르겠네요.

A | B ^ C 에서

(A | B) ^ C 와 A | (B ^ C)의 결과가 다르죠. 보통 논리회로에서 쓰이는 걸로 봐서는 XOR이 OR과 같은 우선 순위여야할 것 같은데... 누구 잘 아시는 분 없나요?

죠커의 이미지

jwhan wrote:
myueho wrote:

틀립니다.
and의 경우 왼항이 false면 오른항을 계산하지 않습니다.

컴파일러 최적화에서 그렇게 하지요. &연산에서는 몇항이 나타나더라도 계산중에 한 항만 false가 나타나도 나머지 항의 계산을 모두 건너뛰고 전체 수식을 false로 처리해 버립니다. | 연산에서는 계산하다가 한 항이라도 true가 나오면 나머지 항을 모두 생략하고 lvalue 에 true를 대입합니다.

똑똑한 컴파일러일수록 최적화때문에 문제가 생기는 경우가 있지요. 계산을 생략한 항이 변수가 아니라 함수이고, side effect를 가지도록 코딩되어 있을때 (즉 비교하면서 메모리를 바꿀때) 해야 할걸 안해버리기 때문에 버그가 되는 경우가 있을 수 있습니다.

short circuit evlauation은 C/C++의 표준입니다.

내 기억으로는 자바나 C#에서도 그럴 것입니다.

죠커의 이미지

tokigun wrote:
사실 연산자 우선순위는 만들기 나름이긴 한데 vacancy 님 말씀처럼 논리곱/논리합이라는 용어 자체에서 순서가 결정된 게 아닌가 싶습니다. ;;; 정확한 자료가 있을 지 모르겠네요.

- 토끼군

표준에서 연산자 우선순위는 최대한 괄호를 안 쓰게 만드는 것이 기준입니다. 용어 자체도 영향을 미쳤지만 현실적으로 논리곱이 우선순위가 높을 경우 괄호를 덜 적게 됩니다.

cppig1995의 이미지

line7979 wrote:
전 '^'(XOR)연산자가 '&'와 '|'사이에 있는지 그게 참 궁금합니다

exclusive해서 새치기를 했어요 (퍼어어어어어어어어억)
윗님 말씀처럼, 확률적 순서가 아닐까 싶네요

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

익명 사용자의 이미지

creativeidler wrote:
XOR은 많은 경우에 OR을 대체해서 쓰이기도 하고 OR과 동작이 비슷하기 때문에 AND보다 낮은 것은 자연스러운 것 같습니다. 하지만 XOR이 OR보다 앞서는 이유는 잘 모르겠네요.

A | B ^ C 에서

(A | B) ^ C 와 A | (B ^ C)의 결과가 다르죠. 보통 논리회로에서 쓰이는 걸로 봐서는 XOR이 OR과 같은 우선 순위여야할 것 같은데... 누구 잘 아시는 분 없나요?

저도 정확한 답은 모르겠습니다만...
|는 inclusive or
XOR는 exclusive or 로 되어 있기 때문에
XOR도 or의 한 종류로 보는게 자연스러운데
inclusive or보다는 논리적으로 복잡한 연산이기 때문에
직관적으로 | 보다는 높은 우선순위를 책정한게
아닌가 싶네요.
(+보다 *가 더 복잡한 연산이므로 *를 더 높은 우선순위에
두고 있는것처럼)

그게 아니면..연산편의성을 위해 그렇게 설정했을수도 있구요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.