[Java] 연산자
by Choi HyeSun
연산자(Operator)
-
연산자(Operator): 연산을 수행하는 기호 (+, -, *, / 등)
-
피연산자(Operand) : 연산의 작업 대상(변수, 상수, 리터럴, 수식)
식(式)
- 연산자와 피연산자를 조합하여 계산을 하는 바를 표현한 것
- 2 * 4
-
식을 계산하여 결과를 얻는 것을 ‘식을 평가(evaluation)한다’라고 함
-
하나의 식을 평가(계산)하면, 단 하나의 결과를 얻음
- 2 * 4 → 8
-
작성한 식을 프로그램에 포함하려면, 식의 끝에 ‘;’를 붙여서 문장으로 만들어야 함
- 2 * 4;
-
대입연산자’=’를 사용하면 변수와 같이 값을 저장할 수 있는 공간에 결과를 저장할 수 있음
- x = 2 * 4;
-
식을 저장하지 않고 출력만 할 경우, println메서드의 괄호()안에 직접 식을 써도 무관
- System.out.println(2*4); → 8 출력
연산자의 기능별 분류
종류 | 연산자 | 설명 |
---|---|---|
산술 연산자 | + - * / % << >> | 사칙 연산과 나머지 연산(%) |
비교 연산자 | > >= < <= == != | 크고 작음과 같고 다름을 비교 |
논리 연산자 | && || ! & | ^ ~ | ‘그리고(AND)’와 ‘또는(OR)’으로 조건을 연결 |
대입 연산자 | = | 우변의 값을 좌변에 저장 |
기타 | (type) ? : instanceof | 형변환 연산자, 삼항 연산자, instanceof 연산자 |
피연산자의 개수에 의한 분류
종류 | 예 | 피연산자 개수 |
---|---|---|
단항 연산자 | (type) a, +a, !a | 피연산자가 한개 |
이항 연산자 | a-b, a<b, a&&b | 피연산자가 두개 |
삼항 연산자 ?: | a?b:c | 피연산자가 세개 |
연산자의 우선순위와 결합규칙(진행방향)
-
산술 > 비교 > 논리 > 대입
-
단항(1) > 이항(2) > 삼항(3)
-
단항 연산자와 대입 연산자를 제외한 모든 연산자의 진행 방향은 왼쪽에서 오른쪽
종류 | 결합규칙 | 연산자 | 비고 | 우선순위 |
---|---|---|---|---|
단항 연산자 | ← | ++ – + - ~ ! (type) | + -는 부호연산자임 | 1 |
산술 연산자 | → | * / % | 2 | |
산술 연산자 | → | + - | 계산 연산자임 | 3 |
산술 연산자 | → | << >> | 4 | |
비교 연산자 | → | < > <= >= | instance of | 5 |
비교 연산자 | → | == != | 6 | |
논리 연산자 | → | & | 7 | |
논리 연산자 | → | ^ | 8 | |
논리 연산자 | → | | | 9 | |
논리 연산자 | → | && | 10 | |
논리 연산자 | → | || | 11 | |
삼항 연산자 | → | ?: | 12 | |
대입 연산자 | → | = += -= *= /= %= | 13 | |
대입 연산자 | ← | «= >>= &= ^= |= | 14 |
일반 산술 변환
-
연산 수행 직전에 발생하는 피연산자의 자동 형변환
-
두 피연산자의 타입을 같게 일치(보다 큰 타입으로 일치)
-
피연산자의 타입이 int보다 작은 타입이면 int로 변환
-
-
증감 연산자는 일반 산술 변환에 의한 자동 형변환이 발생하지 않으며, 연산 결과의 타입은 피연산자와 같음
단항 연산자 : 증감 연산자 ++ –
-
증가 연산자(++) : 피연산자의 값을 1 증가시킴
-
감소 연산자(--) : 피연산자의 값을 1 감소시킴
-
식에 두 번 이상 포함된 변수에 증감 연산자를 사용하는 것은 피해야 함
타입 | 설명 | 사용 예(i = 1) |
---|---|---|
전위형(pretfix) | 값이 참조되기 전에 증가/감소 | j = ++i; → j = 2, i = 2 j = –i; → j = 0, i = 0 |
후위형(postfix) | 값이 참조된 후에 증가/감소 | j = i++; → j = 1, i = 2; j = –i; → j = 1, i = 0; |
단항 연산자 : 부호 연산자 + -
-
- : 피연산자의 부호를 반대로 변경한 결과를 반환
-
-음수 → 양수
-
-양수 → 음수
-
-
+ : 하는 일은 없고, 쓰이는 경우도 없는데 -랑 짝을 맞추기 위해 형식적으로 추가되어있음
- 부호 연산자는 boolean형과 char형을 제외한 기본형에만 사용할 수 있음
산술 연산자 : 사칙 연산자 + - * /
-
+ : 덧셈
-
- : 뺄셈
-
* : 곱셈
-
/ : 나눗셈
-
피연산자가 정수형인 경우, 나누는 수로 0을 사용할 수 없음
0으로 나누면 에러 발생 (ArithmeticException) -
나누기 연산자의 두 피연산자가 모두 int타입인 경우, 연산 결과 역시 int타입 (소수점 아래는 버림)
하나를 float 또는 double로 바꾸고 연산하면 연산 가능 -
피연산자가 하나라도 실수형인 경우, 나누는 수로 0을 사용하면 Infinity(무한대) 출력
-
피연산자가 유한수가 아닌 경우의 연산 결과
-
x | y | x / y | x % y |
---|---|---|---|
유한수 | ±0.0 | ±Infinity | NaN |
유한수 | ±Infinity | ±0.0 | x |
±0.0 | ±0.0 | NaN | NaN |
±Infinity | 유한수 | ±Infinity | NaN |
±Infinity | ±Infinity | NaN | NaN |
-
연산 순서대로 연산을 진행하니 중간에 overflow가 발생하지 않도록 형태에 신경쓰기
-
상수 또는 리터럴 간의 연산은 실행 과정동안 변하는 값이 아니기 때문에, 컴파일 시에 컴파일러가 계산해서 그 결과로 대체함으로써 코드를 보다 효율적으로 만듦
- 즉 풀어 쓰더라도 컴파일러에 의해 미리 계산되므로 실행시 성능 차이는 없음
산술 연산자 : 나머지 연산자 %
-
피연산자로 정수만 허용
- 음수도 허용하지만, 부호는 무시하므로 절댓값으로 나눈 것과 같음
-
주로 짝수, 홀수, 또는 배수 검사 등에 사용
-
나눗셈처럼 나누는 수(오른쪽 피연산자)로 0을 사용할 수 없음
-
왼쪽의 피연산자를 오른쪽 피연산자로 나누고 남은 값
비교 연산자
-
두 피연산자를 비교하는데 사용
-
조건문과 반복문의 조건식에 주로 사용
-
연산결과는 오직 true or false
-
이항 연산자이므로 비교하는 피연산자의 타입이 서로 다를 경우, 자료형의 범위 가 큰 쪽으로 자동 형변환하여 피연산자의 타입을 일치시킨 후 비교
-
(주의) float과 double 비교
-
10.0 == 10.0f → true / 0.1 == 0.1f → false
-
이유 : 정수형과 달리 실수형은 근사값으로 저장되므로 오차가 발생할 수 있음
-
10.0f → 오차없이 저장할 수 있는 값, 0.1f → 2진수로 변환하는 과정에서 오차가 발생
-
10.0f → 0.10000000149011612로 저장
-
0.1f → 0.00000000000000001로 저장
-
성공적으로 비교하려면 : 자동형변환 타입인 float → double로 자동변환되서 비교 (X)
-
성공적으로 비교하려면 : double을 float으로 (수동)형변환 후 비교 (O)
-
-
대소비교
비교 연산자 | 연산결과 |
---|---|
> | 좌변 값이 크면 true 아니면 false |
< | 좌변 값이 작으면 true 아니면 false |
>= | 좌변 값이 크거나 같으면 true 아니면 false |
<= | 좌변 값이 작거나 같으면 true 아니면 false |
- 등가비교
비교 연산자 | 연산결과 |
---|---|
== | 두 값이 같으면 true 아니면 false |
!= | 두 값이 다르면 true 아니면 false |
- 문자열비교
비교 연산자 | 연산결과 |
---|---|
대상문자열.equals(비교문자열) | 대상문자열과 비교문자열이 같으면 true 다르면 false |
대상문자열.equalsIgnoreCase(비교문자열) | 대상문자열과 비교문자열이 대소문자 구분없이 같으면 true 다르면 false |
-
왜 문자열은 ‘==’를 쓰지 않고 .equals를 쓰는가
-
String은 클래스임(참조형 변수) : 값에 값이 들어가지 않고, 주소값이 들어감
==는 주소값끼리 비교를 해버려서 실패 -
주소에 들어있는 값을 비교하려면 .equals()를 사용해야 함
-
String은 클래스지만 new를 사용하지 않고 선언할 수 있도록 허용해 둔 것
-
논리 연산자 : 논리 연산자 && || !
-
|| (or 결합) : 피연산자 중 어느 한 쪽만 true이면 true를 결과로 얻음
-
&& (and 결합) : 피연산자 양쪽 모두 true이어야 true를 결과로 얻음
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이면 우항은 보지 않고 true
-
AND 연산 : 좌항이 false이면 우항은 보지 않고 false
-
위 부분을 고려하여 프로그래밍을 하면 더 빠른 연산 결과를 얻을 수 있음
-
-
! 논리 부정 연산자
-
true → false / false → true 반환
-
단항연산자의 순서는 ← 이렇게 되므로 !!a 일때, a에 가까운 !가 먼저 처리됨
-
논리 연산자 : 비트 연산자 & | ^ ~ << >>
-
비트 연산자는 피연산자를 비트단위로 논리 연산
-
피연산자를 이진수로 표현했을 때 각 자리의 규칙을 규칙에 따라 표와 같이 연산하며, 피연산자로 실수는 허용하지 않고, 정수(문자 포함)만 허용
-
피연산자의 타입을 일치시키는 ‘산술 변환’이 일어날 수 있음
-
규칙
-
| (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 |
ex) 1010 | ex) 1001 | ex) 1011 | ex) 1000 | ex) 0111 |
-
비트 전환 연산자 ~ : 2진수 기준 0 → 1로 1 → 0으로 바꿈
- 논리 부정 연산자 !와 유사
x | ~x |
---|---|
1 | 0 |
0 | 1 |
ex) 1010 | ex) 0101 |
-
쉬프트 연산자 << >>
-
피연산자의 각 자리(2진수로 표현했을때)를 ‘오른쪽(>>)’ 또는 ‘왼쪽(<<)’으로 이동(shift)한다고 해서 ‘쉬프트 연산자(shift operator)
-
좌측 피연산자를 우측 피연산자만큼 쉬프트
-
곱셈/나눗셈 연산자를 사용하지 않고 굳이 쉬프트 연산자를 사용하는 이유?
쉬프트 연산자가 곱셈/나눗셈 연산자보다 빠르기 때문(실행 속도)
가독성이 더 중요하다면 곱셈/나눗셈 연산자로 사용 -
<< (좌측 쉬프트)
-
좌측쉬프트 | ||
---|---|---|
사용법 | a << b | |
의미 | 2진수로 표현했을 때>ba를 b만큼 좌측으로 shift 비는건 0으로 채우기 |
|
예제 | 8 << 2 → 00001000 → 00 |
0001000__ [왼쪽으로 2칸 보내버림] → 0001000__ [삐져나간 값 버림] → 000100000 [비는건 0으로 채우기] = 32 |
비고 | a « b는 a * 2^n의 결과와 같음 (8 « 2 = 8 * 2^2 = 8 * 4 = 32) |
- >> (우측 쉬프트), (단 a >= 0)
우측쉬프트, a>=0 | |
---|---|
사용법 | a >> b (단 a >= 0) |
의미 | 2진수로 표현했을 때 a를 b만큼 우측으로 shift 비는건 0으로 채우기 |
예제 | 8 >> 2 → 00001000 → __000010|00 [오른쪽으로 2칸 보내버림] → __000010 [삐져나간 값 버림] →00000010 [비는건 0으로 채우기] = 2 |
비고 | a >> b는 a / 2^n의 결과와 같음 (8 >> 2 = 8 / 2^2 = 8 / 4 = 2) |
- >> (우측 쉬프트), (단 a < 0)
우측쉬프트, a<0 | ||
---|---|---|
사용법 | a >> b (단 a<0) | |
의미 | 2진수로 표현했을 때 a를 b만큼 우측으로 shift 비는건 음수니까 1로 채우기 |
|
예제 | -8 >> 2 → 11111000 → __111110 |
00 [오른쪽으로 2칸 보내버림] → __111110 [삐져나간 값 버림] →11111110 [비는건 1으로 채우기] = -2 |
비고 | a >> b는 a / 2^n의 결과와 같음 (-8 >> 2 = -8 / 2^2 = -8 / 4 = -2) |
그 외의 연산자 : 조건 연산자 ?:
-
조건식 ? 식1 : 식2
- 조건식이 참(true)면 식1, 거짓(false)면 식2
-
가독성을 높이기 위해 조건식을 괄호( )로 둘러싸는 경우가 많지만 필수는 아님
-
가독성이 떨어지기 때문에 꼭 필요한 경우에 한 번 정도만 중첩하는 것이 좋음
-
조건 연산자의 식1과 식2의 피연산자 타입이 다른 경우, 이항연산자처럼 산술 변환이 일어남
-
if문의 다음과 같음
그 외의 연산자 : 대입 연산자 = op=
-
대입 연산자 (=)
-
lvalue(left value) : 대입 연산자의 왼쪽 피연산자, 값을 변경할 수 있는 것
-
rvalue(right value) : 대입 연산자의 오른쪽 피연산자, 변수, 상수, 식, 리터럴 등 모두 가능
-
왼쪽 피연산자의 값을 오른쪽 피연산자에 저장
-
우선순위가 가장 나중이고, 결합방향이 ← 임
-
y = x = 3 : x = 3부터 진행 후 y = x 진행
-
-
복합 대입 연산자 (op =)
-
대입 연산자는 다른 연산자(op)와 결합하여 “op=”와 같은 방식으로 사용될 수 있음
-
결합된 두 연산자는 반드시 공백 없이 붙여써야 함
-
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); (틀림 - i = i * 10 + j); |
Subscribe via RSS