본문 바로가기
Study/JAVA

[Java] 3-3,4,5,6. 산술 & 비교 & 논리 & 그 외 연산자

by jeongwle 2022. 8. 30.
728x90
반응형

 

산술 연산자

1. 사칙 연산자 + - * /

사칙 연산자는 이미 잘 알고 있을 것이다. 피연산자가 정수형인 경우 나누는 수로 0을 사용할 수 없다. 하지만 부동 소수점값인 0.0f, 0.0d로 나누는 것은 가능하지만 그 결과는 Infinity(무한대)이다.

 

2. 나머지 연산자 %

나머지 연산자는 왼쪽의 피연산자를 오른쪽의 피연산자로 나누고 난 나머지 값을 결과로 반환하는 연산자이다. 나머지 연산자는 주로 짝수, 홀수 또는 배수 검사 등에 주로 사용된다.

나머지 연산자는 나누는 수로 음수도 허용한다. 하지만 부호는 무시되므로 음수의 절대값을 나눈 나머지와 결과가 같다.

 

 

비교 연산자

1. 대소비교 연산자 <  >  <=  >=

두 피연산자의 값의 크기를 비교하는 연산자로 참이면 true, 거짓이면 false를 결과로 반환한다. 기본형 중에서 boolean형을 제외한 나머지 자료형에 사용할 수 있지만 참조형에는 사용할 수 없다.

 

2. 등가비교 연산자 ==  !=

두 피연산자의 값이 같은지 또는 다른지를 비교하는 연산자이다. 기본형은 물론 참조형, 즉 모든 자료형에 사용할 수 있다. 기본형의 경우 변수에 저장되어 있는 값이 같은지를 알 수 있고, 참조형의 경우 객체의 주소값을 저장하기 때문에 두 개의 피연산자가 같은 객체를 가리키고 있는지를 알 수 있다. 기본형과 참조형은 서로 형변환을 할 수 없기 때문에 기본형과 참조형을 비교할 수는 없다. 비교 연산자 또한 이항 연산자이므로 연산을 수행하기 전에 형변환을 통해 두 피연산자의 타입을 같게 맞춘 다음 피연산자를 비교한다.

두 문자열을 비교할 때는 == 대신 equals()라는 메서드를 사용해야 한다. 비교 연산자는 두 문자열이 완전히 같은 것인지 비교할 뿐이다. 문자열의 내용이 같은 지 비교하기 위해서는 equals()를 사용해야 한다. equals()는 비교하는 두 문자열이 같으면 true, 다르면 false를 반환한다.

public class OperatorEx23 {
    public static void main(String[] args) {
        String str1 = "abc";
        String str2 = new String("abc");

        System.out.println("abc == abc ? " + ("abc" == "abc"));
        System.out.println("str1 == abc ? " + (str1 == "abc"));
        System.out.println("str2 == abc ? " + (str2 == "abc")); // 내용은 같지만 서로다른 객체
        System.out.println("str1.equals(\"abc\") ? " + str1.equals("abc"));
        System.out.println("str2.equals(\"abc\") ? " + str2.equals("abc"));
        System.out.println("str2.equals(\"ABC\") ? " + str2.equals("ABC"));
        System.out.println("str2.equalsIgnoreCase(\"ABC\") ? " + str2.equalsIgnoreCase("ABC"));
    }
}​

str2와 "abc"의 내용이 같지만 ==로 비교하면 false가 나온다. 내용은 같지만 서로 다른 객체라서 그렇다. 그러나 equals()는 서로 다른 객체라 하더라도 내용이 같으면 true를 반환한다. equalsIgnoreCase()는 대소문자를 구별하지 않고 내용을 비교해준다.

 

 

논리 연산자

1.논리 연산자 &&  ||  !

논리 연산자 &&는 그리고(AND)에 해당하며 두 피연산자 모두 true일 때만 true를 결과로 얻는다. ||는 또는(OR)에 해당하며 두 피연산자 중 한 쪽만 true이어도 true를 결과로 얻는다. 그리고 논리 연산자는 피연산자로 boolean형 또는 boolean형 값을 결과로 하는 조건식만을 허용한다.

x y x || y x && y
true true true true
true false true false
false true true false
false false false false
&& 연산이 || 연산보다 우선순위가 높다는 것을 기억하자.

효율적인 연산(short circuit evaluation)
논리 연산자의 또 다른 특징은 효율적인 연산을 한다는 것이다. OR연산 ||의 경우 두 피연산자중 하나만 참이어도 전체 연산결과가 참이기 때문에 좌측 피연산자가 true일 경우 우측 피연산자의 값은 평가하지 않는다.

AND연산 &&의 경우도 마찬가지로 어느 한쪽만 거짓이어도 전체 연산결과가 거짓이기 때문에 좌측 피연산자가 false일 경우 우측 피연산자의 값은 평가하지 않는다.

그래서 같은 조건식이라도 피연산자의 위치에 따라서 연산속도가 달라질 수 있는 것이다.

논리 부정 연산자 !
이 연산자는 피연산자가 true이면 false를, false면 true를 결과로 반환한다.

 

2. 비트 연산자 &  |  ^  ~  <<  >>

비트 연산자는 피연산자를 비트단위로 논리 연산한다. 피연산자를 이진수로 표현했을 때의 각 자리를 규칙에 따라 연산을 수행하며, 피연산자로 실수는 허용하지 않는다. 정수(문자 포함)만 허용된다.

| (OR연산자) => 피연산자 중 한 쪽의 값이 1이면 1을 결과로 얻고 그 외에는 0을 얻는다.
& (AND연산자) => 피연산자 양쪽 모두 1이어야만 1을 결과로 얻고 그 외에는 0을 얻는다.
^ (XOR연산자) => 피연산자의 값이 서로 다를 때만 1을 결과로 얻고 같을 때는 0을 얻는다.

x y x | y x & y x ^ y
1 1 1 1 0
1 0 1 0 1
0 1 1 0 1
0 0 0 0 0

비트 전환 연산자 ~
이 연산자는 피연산자를 2진수로 표현했을 때 0은 1로, 1은 0으로 바꾼다. 논리부정 연산자 !와 유사하다. 비트 전환 연산자 ~ 에 의해 비트 전환되고 나면, 부호있는 타입의 피연산자는 부호가 반대로 변경된다. 즉, 피연산자의 1의 보수를 얻을 수 있는 것이다. 그래서 비트전환연산자를 1의 보수 연산자라고도 한다.

예를 들어 10진수 10을 비트전환 연산한 결과는 -11이고 이미 배운 것과 같이 1의 보수에 1을 더하면 음수가 되므로 -11에 1을 더하면 -10이 되고 -11은 10의 1의보수가 맞다는 것을 확인할 수 있다.

쉬프트 연산자 <<  >>
이 연산자는 피연산자의 각 자리(2진수로 표현했을 때)를 오른쪽(>>) 또는 왼쪽(<<)으로 이동(shift)한다고 해서 쉬프트 연산자(shift operator)라고 이름 붙여 졌다. 예를 들면 8 << 2는 왼쪽 피연산자인 10진수 8의 2진수를 왼쪽으로 2자리 이동한다.

x << n 은 x * 2ⁿ의 결과와 같다.
x >> n 은 x / 2ⁿ의 결과와 같다.

곱셈이나 나눗셈 연산자를 사용하면 같은 결과인데 쉬프트 연산자를 제공하는 이유는 속도 때문이다. 쉬프트 연산자가 곱셈이나 나눗셈 연산자보다 속도가 빠르다. 하지만 코드의 가독성이 떨어질 수 있기 때문에 빠른 실행속도가 요구되어지는 곳만 쉬프트 연산자를 사용하는 것이 좋다.

 

그 외의 연산자

1. 조건 연산자 ?:

조건 연산자는 조건식, 식1, 식2 모두 세 개의 피연산자를 필요로 하는 삼항 연산자이며 삼항 연산자는 조건 연산자 하나 뿐이다.

조건 연산자는 첫 번째 피연산자인 조건식의 평가결과에 따라 다른 결과를 반환한다. 조건식의 평가결과가 true이면 식1이, false이면 식2가 연산결과가 된다. 가독성을 높이기 위해 조건식을 괄호()로 둘러싸는 경우가 많지만 필수는 아니다.
result = (x > y) ? x : y ;​


x > y 가 true일 경우 result에 x가 저장되고 false일 경우엔 result에 y가 저장된다.

// 위 삼항 연산자는 밑의 if문과 똑같다.
if (x > y)
  result = x;
else
  result = y;


조건 연산자를 여러 번 중첩하면 코드가 간략해지긴 하지만 가독성이 떨어지므로 꼭 필요한 경우에 한번 정도만 중첩하는 것이 좋다.

그리고 조건 연산자의 식1과 식2, 이 두 피연산자의 타입이 다른 경우, 이항 연산자처럼 산술 변환이 발생한다.

x = x + (mod < 0.5 ? 0 : 0.5) // 0과 0.5의 타입이 다르다.
-> x = x + (mod < 0.5 ? 0.0 : 0.5) // double타입으로 통일되고 연산결과 역시 double타입이 된다.

 

2. 대입 연산자 =  op=

대입 연산자는 변수와 같은 저장공간에 값 또는 수식의 연산결과를 저장하는데 사용된다. 그리고 저장된 값을 연산결과로 반환한다.

lvalue와 rvalue
대입 연산자의 왼쪽 피연산자를 lvalue(left value)라 하고 오른쪽 피연산자를 rvalue(right value)라고 한다. 대입연산자의 rvalue는 변수뿐만 아니라 식이나 상수 등이 모두 가능한 반면, lvalue는 반드시 변수처럼 값을 변경할 수 있는 것이어야 한다. 그래서 리터럴이나 상수같이 값을 저장할 수 없는 것들은 lvalue가 될 수 없다.

복합 대입 연산자
대입 연산자는 다른 연산자(op)와 결합하여 op= 와 같은 방식으로 사용될 수 있다. 예를 들면 i = i +3 => i +=3 과같이 표현할 수 있다. 그리고 결합된 두 연산자는 반드시 공백없이 붙여써야 한다.

op= =
i += 3; i = i + 3;
i -= 3; i = i - 3;
i *= 3; i = i * 3;
i /= 3; i = i / 3;
i %= 3; i = i % 3;
i <<= 3; i = i << 3;
i >>= 3; i = i >> 3;
i &= 3; i = i & 3;
i ^= 3; i = i ^ 3;
i |= 3; i = i | 3;
i *= 10 + j; i = i * (10 + j);
복합 연산자가 잘 익숙해지지 않는다면, 오른쪽과 같은 형태의 식을 사용하다가 점차 왼쪽의 형태로 바꿔가도록 하자. 그리고 마지막 줄 처럼 우변이 둘 이상의 항으로 이루어져 있는 경우이다. 잘 살펴보자.

 

 

728x90
반응형

'Study > JAVA' 카테고리의 다른 글

[Java] 5. 배열(Array)  (0) 2022.09.01
[Java] 4. 조건문과 반복문  (0) 2022.08.31
[Java] 3-2. 단항 연산자  (0) 2022.08.30
[Java] 3-1. 연산자  (0) 2022.08.30
[Java] 2-5. 형변환  (0) 2022.08.03

댓글