6 분 소요

자바에서 사용할 수 있는 연산자들에 대해 살펴보자.

산술 연산자

연산자 설명
+ 덧셈 1+2=3
- 뺄셈 2-1=1
* 곱셈 2*3=6
/ 나누기 몫 7 / 3 = 2
% 나누기 나머지 7 % 3 = 1
public class ArithmeticOperators {
    public static void main(String[] args) {
        int a = 11;
        int b = 4;

        System.out.println("a : " + a);
        System.out.println("b : " + b);
        System.out.println("덧셈 : " + (a + b));
        System.out.println("뺄셈 : " + (a - b));
        System.out.println("곱셈 : " + (a * b));
        System.out.println("나눗셈의 몫 : " + (a / b));
        System.out.println("나눗셈의 나머지 : " + (a % b));
    }
}

a : 11
b : 4
덧셈 : 15
뺄셈 : 7
곱셈 : 44
나눗셈의  : 2
나눗셈의 나머지 : 3

대입 연산자

자바에서 대입 연산자는 등호 기호(=)로, 오른쪽 항의 데이터를 왼쪽 항의 변수에 할당한다.

char alp = 'A';

또한, 복합 대입 연산자도 존재한다.

연산자 같은 표현
a += b a = a + b
a -= b a = a - b
a *= b a = a * b
a /= b a = a / b
a %= b a = a % b

위 표에서, 오른쪽 열에 있는 일반적인 대입 방법과 달리, 복합 대입 연산자만의 특징은, 두 피연산자들의 자료형이 다를 경우, 강제 형변환이 필요하지 않다는 것이다. 즉, 자동 형변환이 일어난다. 위 표의 오른쪽 열과 같이 일반 대입 연산자를 이용한다면, 두 피연산자의 자료형이 다를 때, 왼쪽 항의 변수에 오른쪽 연산 결과값을 할당하고자 한다면 강제 형변환이 필요하다.

public class AssignOperators {
    public static void main(String[] args) {
        // 복합 대입 연산자 예
        int a = 1;
        a += 10l;  // 자동 형변환
        System.out.println(a);

        a = (int)(a + 20l); // 강제 형변환
        System.out.println(a);
    }
}

11
31

부호 연산자

부호 연산자는 숫자의 양수, 음수를 나타낼 때 사용되는 연산자이다.

public class signOperator {
    public static void main(String[] args) {
        int positive = +1;
        int negative = -1;
        int normal = 1;

        System.out.println(positive);
        System.out.println(negative);
        System.out.println(normal);
        System.out.println(positive == normal); // positive와 normal은 같은가?
    }
}

1
-1
1
true

숫자 앞에 + 기호를 생략해도 해당 숫자는 양수로 인식된다. (이는 수학에서도 동일하다)

증감 연산자

숫자 데이터 앞이나 뒤에 ‘+’ 기호 또는 ‘-’ 기호를 두 번 연속 작성한 ‘++’, ‘--’ 기호는 각각 해당 숫자를 1만큼 증가 또는 감소시키는 연산자이다. 그런데 숫자 데이터의 앞에 쓰느냐 뒤에 쓰느냐에 따라 증감 효과 적용 순서가 바뀐다. 다음 예제를 보자.

public class incDecOperator {
    public static void main(String[] args) {
        // 증감 연산자 관련 예제
        int a = 10;
        int b = a++;
        int c = ++a;

        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
    }
}

12
10
12

int b = a++; 코드를 보면, a 변수 뒤에 ‘++’라는 증가 연산자가 쓰였다. 이렇게 증가 연산자가 숫자 데이터의 뒤에 붙으면, 먼저 변수 b에 a의 값을 대입하는 연산이 먼저 진행된다. 그 후에 변수 a의 값이 1 증가한다. 위 예제에서는 변수 b의 선언과 할당이 이뤄지면 b = 10, a = 11인 상태이다. 그 다음, int c = ++a; 코드를 만나면, 증가 연산자 ‘++’가 변수 a의 앞에 붙어있다. 이 경우 아까와는 다르게 연산 순서가 바뀐다. 즉, a의 값이 먼저 1 증가한 다음, 그 후에 변수 c에 a의 값이 할당된다. 따라서 a가 12가 된 후에 그 12가 변수 c에 할당된다. 따라서 위와 같은 결과가 나온다.

즉, 정리하면 다음과 같다.

  • ++a, --a 와 같이 증감 연산자가 숫자 데이터 앞에 존재하는 경우, 해당 숫자가 먼저 1 증가(또는 감소)한 뒤에 다른 연산이 뒤이어 진행된다.
  • a++, a--와 같이 증감 연산자가 숫자 데이터 뒤에 존재하는 경우, 다른 연산이 먼저 진행된 뒤에 a의 값이 1 증가(또는 감소)한다.

비교 연산자 (관계 연산자)

비교 연산자는 두 피연산자를 비교한 결과에 따라 true 또는 false를 반환한다.

연산자 설명
== 두 피연산자의 값이 같으면 true, 아니면 false를 반환.
!= 두 피연산자의 값이 다르면 true, 아니면 false를 반환.
> a > b ⇒ a가 b보다 크면 true, 아니면 false를 반환.
>= a >= b ⇒ a가 b보다 크거나 같으면 true, 아니면 false를 반환.
< a < b ⇒ a가 b보다 작으면 true, 아니면 false 반환.
<= a <= b ⇒ a가 b보다 작거나 같으면 true, 아니면 false를 반환.

논리 연산자

연산자 설명 예시
&& 논리곱, And. 두 항이 모두 true이면 true를, 하나라도 false면 false를 반환. (1!=2) && (1>=2) ⇒ true
|| 논리합, Or. 두 항 중 하나라도 true이면 true, 모두 거짓이면 false를 반환 (3%2==0) || (3 > 2) ⇒ false
! 부정, Not. 값이 true이면 false를, 값이 false면 true로 변환. !(2==2) = false

참고. 0을 false, 0을 제외한 나머지 수를 true라 생각하면… 논리곱의 경우. 우선 논리곱 대신 곱셈 연산을 각각 해본다면…

1 * 1 = 1
1 * 0 = 0
0 * 1 = 0
0 * 0 = 0

그런데 위 결과에서 곱셈 연산을 && 연산자로 변경해도 성립된다. 논리곱이 헷갈리면 이렇게 알아둬도 기억하기 쉬울 것이다. 논리합에 대해서도, 먼저 덧셈 연산에 대해 진행해보면…

1 + 1 = 2
1 + 0 = 1
0 + 1 = 1
0 + 0 = 0

여기서, 보통의 프로그래밍 언어들에서 그러하듯, 0을 false, 0 이외의 모든 수를 true라 가정한다면, 위 표에서 덧셈 연산을 논리합(||) 연산자로 변경해도 성립된다. 논리합의 경우의 수가 헷갈린다면 위와 같이 생각하면 기억하기 쉬울 것이다.

논리 연산자는 비교 연산자와 합쳐 쓰면 조건문으로 사용할 수 있음을 알 수 있다.

Short-Circuit Evaluation (최단 거리 평가, SCE)

자바스크립트에서 JS - [기본 문법] 조건문 (해당 페이지 준비 중) 의 “단축 평가” 챕터에서도 같은 이야기를 언급하였다.

true 또는 false를 반환하는 어떤 비교 연산식 A, B가 있다고 가정해보자. 그러면 논리곱의 경우, A && B 가 있다면, A만 false이면 그 뒤에 B가 true이든 false이든 상관없이 자동으로 해당 논리 연산식은 false가 된다. 그래서 B의 연산 결과를 굳이 알 필요가 없어진다. 논리합도 마찬가지로, A || B가 있을 때, A가 true이면, B가 true이든 false이든 상관없이 해당 논리 연산 결과는 자동으로 true로 결정된다. 따라서 이러한 경우, 그 뒤의 B 연산식은 연산이 수행되지 않아도 된다. 이는 자바에서도 마찬가지이다. 즉, 위와 같은 경우일 경우, 논리 연산자 뒤의 연산식은 연산되지 않고 다음으로 넘어간다. 이러한 현상을 Short-Circuit Evalution이라 한다.

정말로 SCE 현상이 사실일까? 다음의 코드를 보자.

public class SCE {
    public static void main(String[] args) {
        // Short-Circuit Evalution 예제
        int math = 90;
        int english = 95;

        // 조건문 1
        if (math++ % 2 == 0 || english++ % 2 == 0) {
            System.out.println("적어도 점수 하나는 짝수이다.");
        } else {
            System.out.println("모든 점수가 홀수이다.");
        }
        System.out.println("math: " + math);
        System.out.println("english: " + english);
        System.out.println("=========");

        // 조건문 2
        if (math++ >= 100 && english++ >= 100) {
            System.out.println("점수가 이상합니다.");
        }
        System.out.println("math: " + math);
        System.out.println("english: " + english);
    }
}

적어도 점수 하나는 짝수이다.
math: 91
english: 95
=========
math: 92
english: 95

위 코드에서 만약 SCE 현상이 존재하지 않았다면, 각 논리 연산자 뒤의 연산식도 실행되었을 것이다. 즉, english++ 연산이 실행되어 english 변수값도 초기값보다 증가했을 것이다. 그런데 위 코드의 실행결과를 보면 math 변수값의 값만 증가하였을 뿐, english 변수값은 전혀 증가되지 않았음을 알 수 있다. 각각 논리 연산자의 앞에 나오는 연산식만 보고, 해당 연산식의 boolean 결과값이 논리 연산식의 전체값을 결정한다면 그 뒤의 연산식은 실행되지 않음을 알 수 있다.

이는 논리 연산자의 뒤에 존재하는 연산식도 실행되었을 때에 비하면 상대적으로 연산 속도가 빠를 것이다. 따라서 위 사실을 잘 이용하여 논리곱의 경우, false 값이 나올 가능성이 높은 연산식을 맨 앞에 배치하거나, 논리합의 경우, 결과값이 true가 나올 가능성이 높은 연산식을 맨 앞에 배치하면 전체적인 연산 속도를 조금이라도 더 높일 수 있겠다.

조건 연산자

조건 연산자는 총 3개의 항을 사용하는 삼항 연산자로, 조건식이 참일 때와 거짓일 때의 경우에 따라 실행되는 것이 달라지는 연산자이다. 형태는 다음과 같다.

조건식 ? 참일  실행 : 거짓일  실행;

다음은 조건 연산자를 활용하여 두 수의 양의 차를 구하는 예제이다.

public class condOperator {
    public static void main(String[] args) {
        // 조건 연산자 예제.
        int a = 10;
        int b = 20;

        // 조건 연산자를 이용하여 두 수의 양의 차이를 구한다. 
        // 조건식 ? 참일 경우 실행 : 거짓일 경우 실행;
        int positiveDiff = (a > b) ? (a - b) : (b - a);
        // 조건식 (a > b)가 거짓이므로, (b - a)식이 실행된 결과값이 해당 변수에 할당됨.
        System.out.println(positiveDiff);
    }
}

10

References

[1] 이재환, “이재환의 자바 프로그래밍 입문”, (골든래빗, 2021)

This content is licensed under CC BY-NC 4.0

댓글남기기