본문 바로가기

Coda Study

논리 연산, 불리언대수, 드모르간 법칙

컴퓨터 공학에서의 논리 연산은 불리언 대수(Boolean algerbra)라고도 알려진 수학적 체계를 기반으로 한다고 합니다.
불리언 대수는 논리적인 참과 거짓의 값을 다루는 대수적인 구조를 제공하여 논리 연산을 수행합니다

이번 글에서는 논리연산, 불리언대수, 드모르간 법칙에 대해서 설명하고자 합니다.

논리 연산이란?

참(TRUE)과 거짓(FALSE) 두 가지 값만으로 연산하는 것입니다.
즉, 연산자들을 여러 조건을 조합하여 하나의 참/거짓 결과를 도출하며, 주로 코딩에서 조건문 등에 활용됩니다.


주요 연산자

  • AND 연산자
    • 두 개의 조건 중 하나라도 참이면 참
      true && true == true, true && false == false
    • C, Java에서'&&'기호 사용하고 Python에서는 'and'키워드 사용합니다.
  • OR 연산자
    • 두 개의 조건 중 하나라도 참이면 참
      true || false == true
    • C, Java에서는 '||' 기호로 사용하고 Python에서는 'or' 키워드 사용합니다.
  • NOT 연산자
    • 참을 거짓으로, 거짓을 참으로 바꿔줌
      !false == true
    • C, Java에서 '!' 기호 사용하고 Python에서는 'not'키워드 사용합니다.

불리언대수

불대수는 어떤 명제의 참과 거짓을 이진수를 사용하여 수학적으로 표현하는 방법입니다.

논리 연산자를 사용하여 불리언 값들을 조합하고 조작하는 데 사용됩니다.

불 대수의 기본 법칙

  • 교환법칙: A + B = B + A, A ⋅ B = B ⋅ A
  • 결합법칙: (A + B) + C = A + (B + C)
  • 분배법칙: A ⋅ (B + C) = (A ⋅ B) + (A ⋅ C)
  • 드 모르간의 법칙: ¬(A ⋅ B) = (¬A) + (¬B) , ¬(A + B) = (¬A) ⋅ (¬B)
  • 흡수 법칙: A + A ⋅ B = A, A ⋅ (A + B) = A
  • 합의 법칙: AB + BC + ¬(A)C = AB + ¬(A)C

드모르간 법칙

불리언 대수에서 중요한 개념으로, 논리 연산자들 간의 상호 변환 관계를 설명합니다.

한마디로 논리식을 더 단순화하고 변환하는 하여 복잡한 논리식을 더 간결하고 이해하기 쉬운 형태로 표현할 수 있습니다.

논리곱(&&)과 논리합(||) 연산을 부정(NOT)할 때, 부정 연산자가 각 항으로 들어가면서 AND는 OR로, OR은 AND로 바뀌는 법칙입니다.

  • 첫 번째 법칙: ¬(A ∧ B) = (¬A) ∨ (¬B)
    즉, A AND B의 부정은 A의 부정 OR B의 부정과 같습니다.
  • 두 번째 법칙: ¬(A ∨ B) = (¬A) ∧ (¬B)
    즉, A OR B의 부정은 A의 부정 AND B의 부정과 같습니다.

드모르간 법칙의 활용의 예

1) 범위 체크

!(a && b) → !a || !b

 // Before: "0~100 사이가 아니면"을 부정으로 표현
if (!(0 <= x && x <= 100)) {
    puts("out of range");
}

// After: 드모르간 적용 → 더 직관적
if (x < 0 || x > 100) {
    puts("out of range");
}

2) 포인터/문자열 루프

!(p==NULL || *p=='\0') → p && *p

// Before
while (!(p == NULL || *p == '\0')) {
    /* 처리 */
    p++;
}

// After
while (p && *p) {
    /* 처리 */
    p++;
}

3) “금지 문자 없음” 검사

!(A || B || C) → !A && !B && !C

// 공백/탭/개행이 "아니어야" 할 때

// Before
if (!(ch == ' ' || ch == '\t' || ch == '\n')) {
    /* 허용 문자 처리 */
}

// After
if (ch != ' ' && ch != '\t' && ch != '\n') {
    /* 허용 문자 처리 */
}

핵심:

  • !(A && B) → !A || !B
  • !(A || B) → !A && !B

이렇게 바꾸면 부정의 괄호를 없애고, 조건 의도가 더 분명해져서 코드가 간결해집니다.