JAVA

자바 JAVA 연산자와 자동 형변환 & 오버플로우 / 언더플로우

수진97 2025. 11. 23. 12:32

안녕하세요~!

이번 포스팅은 자바 연산자에 대해 총 정리하고, 자동 형변환과 오버플로우 / 언더플로우 개념에 대해서도 함께 살펴보겠습니다.

1. JAVA 연산자 종류

1) 형변환 연산자

(cast) 하나의 항을 형 변환해 주는 연산자

 

* 자동 형변환

작은 타입 -> 큰 타입으로 자동 변환

(byte -> short -> int -> long -> float -> double)

 

연산 시 피연산자 중 큰 자료형으로 자동 승격

실제 타입 확인 : Object로 저장 후 .getClass().getName()

 

 

 

2) 산술 연산자

+, -, *, /, %, +=, -=, *=, /=, %=

항 두 개나 좌우의 항을 더하거나 빼는 등 가장 기본 연산을 하는 연산자

 

- 단항 연산자(Unary Operator) : ++a, a--, ! flag 등등.. (피연산자 1개)

전위형(++x) : 즉시 증가 후 사용

후위형(x++) : 사용 후 증가

 

* 연산자 바로 뒤에 나오는 것부터 먼저 수행한다고 생각하면 쉬움.(계산 순서 유의)

result = number++; => 대입연산자(=) 뒤에 number 변수가 먼저 나왔으므로 result에  number값 대입 후 ++

result = --number; => -- 가 먼저 나왔으므로 number값에 -1을 한 후 그 값을 result에 대입

 

EX. result = number++ + number--

1> 첫 번째 number값 5 (++ 전 값)

2> number ++로 인해 6이 된 두 번째 number값(-- 전 값)

3> 1,2번에 의해 두 number 값을 더한 값이 최종 result = 11

4> 이후 number값 - 1 해서 최종 number는 5

 

 

- 이항 연산자(Binary Operator) : +, -, ==, >, &&, ||, %=, &, ^ 등등.. (피연산자 2개)

- 다항 연산자(Ternary Operator) : 조건식 ? 값 1 : 값 2 (삼항 연산자)

 

 

- 기본 산술 연산자 : +, -, *, /, %

- 복합 대입 연산자 : *=, %=

 

 

** 주의 **

실수형 계산에서는 소수점 주의 (ex. 1 / 1000.0 = 0.001)

정수형 나눗셈은 소수점 이하 버림

기본적으로 피연산자 중에서 데이터 타입이 큰 쪽을 따라 결과가 출력되도록 설계됨. (ex. 실수 / 정수 = 실수)

=> 나누기와 곱하기 연산 수행 시 많은 주의 필요

 

정수와 정수의 나누기 => 정수

정수와 실수의 나누기 => 실수

산술연산 할 때 연산 결과가 버림 현상이 발생하지 않는지 체크

float 데이터 타입을 활용해 나눗셈 수행 시, 소수점 이하의 오차율이 커지지 않는지 체크

곱하기 연산 시 오버플로우 or 언더플로우 발생여부 체크

 

두 가지 버전 풀이 비교

 

- N이 0이거나 M이 0일 경우 나누기 연산 수행 시 에러 발생하므로 if문 앞으로 빼야 함.

- 이 문제에서 주어진 범위가 10^18이기 때문에 단순히 (2 * M)을 계속해서 빼는 경우 시간 초과 발생

- (2 * M)을 몇 번 빼주면 되는지 미리 계산 후  한 번에 빼면 시간 단축

- 좀 더 확장해서 % (Mod 연산) 수행을 통해 좀 더 단순하게 문제 풀이 가능

 

 

 

3) 관계 연산자

>, <, >=, <=, ==, !=

두 피연산자 사이 대소관계 혹은 동등의 정도를 측정하는 연산자

관계 연산자의 결과는 True / False 중 하나

따라서 관계 연산자는 조건문과 결합해 다양하게 활용됨.

 

백준 14681번 사분면 고르기

 

 

4) 비트 연산자

&, ^, |, <<, >>, <<=, >>=, ^=, &=, |=


정수형 피연산자를 대상으로 비트 단위로 연산 수행

주로 비트를 0과 1로 끄고 키는 연산이나 비트 단위로 전후로 이동해 결과를 내는 연산자

 

* 비트

- 컴퓨터가 나타내는 데이터 최소단위

- 2진수 값 하나 저장할 수 있는 메모리 공간

- 모든 정수는 비트 값의 집합으로 변환되어 저장됨.

 

AND(&) : 논리 연산자의 논리곱 연산과 동일. 특정 비트에서 정보를 추출할 때 많이 사용 (모두 1이면 1)

OR(|) : 논리 연산자의 논리합 연산과 동일. 특정 비트 정보를 1로 변환할 때 많이 사용(모두 0이면 0)

출처 : http://www.tcpschool.com/c/c_operator_bitwise

 

 

XOR(^) : 두 개 피연산자 각 비트에 대해 XOR 연산 수행. (각 비트값이 서로 다르면 1, 같으면 0 반환) => 입력 피연산자의 정보를 임의로 변환하고, 다시 복원할 수 있는 특징이 있어 암호 프로그램에서 다양하게 응용(암호화 / 복호화)됨.

NOT(~) : 두 개 피연산자 각 비트에 대해 해당 비트가 0이면 1 반환, 1이면 0 반환.

출처 : http://www.tcpschool.com/c/c_operator_bitwise

 

* 활용 예제

권한 추가(OR |) 사용 : 비트 켜기 

권한 확인(AND &) : 해당 비트가 켜져 있는지 확인 

권한 삭제(AND & + NOT ~) : 해당 비트만 끄기

 

 

시프트 연산자(<<, >>, >>>)

=> 정수에 들어 있는 모든 비트를 오른쪽이나 왼쪽으로 이동하는 연산자

오른쪽 피연산자만큼 왼쪽 피연산자의 모든 비트를 오른쪽(>>)으로 이동 -> / 2

오른쪽 피연산자만큼 왼쪽 피연산자의 모든 비트를 왼쪽(<<)으로 이동 -> X2

 

>>> 의 경우 오른쪽 피연산자만큼 왼쪽 피연산자의 모든 비트를 오른쪽으로 이동시키고, 왼쪽은 0으로 채움

(부호 비트가 왼쪽에 0으로 채워지기 때문에 결과는 항상 양수가 되므로 부호 없는 오른쪽 시프트임)

 

>> 는 부호 있는 오른쪽 시프트로, 음수의 경우 부호 비트(1)가 유지되기 때문에 결과도 음수지만,

>>>는 부호 없는 오른쪽 시프트로, 부호 비트가 0으로 바뀌기 때문에 음수가 양수로 바뀜.

 

 

5) 논리 연산자

&&, ||, &, ^, |, !, [조건] ? [true] : [false]

두 피연산자의 논리적 관계를 정의하는 연산자 => 항 두 개를 비교하여 true와 false의 결과를 연산

조건문의 조건식으로 많이 이용

 

^ (XOR)

연산자를 기준으로 왼쪽과 오른쪽에 하나 이상, 두 개의 피연산자가 존재하며, 두 값이 서로 다를 때만 true를 반환.

그렇지 않으면 즉, 같을 때는 false를 반환

 

 

조건식 ? [true] : [false]  (삼항 연산자)

조건 연산자로써 피연산자 즉, 조건식이 true일 때, [true] 수행, 조건식이 false일 때, [false] 수행

 

 

논리곱(AND) && 와 & 차이 (OR 논리합 연산자 || 와 | 차이)

모든 논리 연산은 왼쪽에서 오른쪽으로 순차적으로 해석하는데, 

&&은 첫 번째 피연산자가 거짓일 경우, 두 번째 피연산자 평가하지 않고 결과 바로 반환

&는 첫 번째 피연산자가 거짓이라도 두 번째 피연산자까지 모두 평가 후 결과 반환

 

||도 마찬가지로 첫 번째 연산자가 참일 경우, 뒤에 보지 않고 결과 바로 반환

|는 왼쪽 결과 참이어도, 양쪽 피연산자 모두 평가 후 결과 반환

 

백준 25593번 근무 지옥에 빠진 푸앙이 (Small)

 

 

6) 연산자 우선순위

- 다양한 연산자가 결합되었을 때 어떤 순서로 계산을 수행할지 결정하기 위해 연산자 우선순위 필요

- 자바에서 지원하는 연산자 우선순위 정의(우선순위가 같은 연산자의 경우, 왼쪽에 사용된 연산자가 우선순위가 더 높음)

출처 : https://toma0912.tistory.com/66

 

 

 

2. 오버플로우 / 언더플로우

1) 오버플로우

- 변수가 표현할 수 있는 최대 범위 초과 시 

- 너무 큰 양수나 너무 작은 음수 할당 시 

 

- 주로 정수형 변수(int, long)에서 발생

- int 최댓값(약 21억) 초과 OR 최솟값(약 -21억) 미만일 때 => long 사용

ex) int result = 1000000000 * 10000000000;

 

=> 저장 가능한 최댓값을 초과할 때 오버플로우. 값이 최솟값으로 순환(wrap-around)

 

 

 

2) 언더플로우 

- 부동 소수점 수에서 매우 작은 값이 정확하게 표현되지 않아 0으로 처리될 때 발생

- 정수형 연산에서는 발생하지 않음. 부동 소수점 연산에서 관찰됨.

 

- 주로 부동 소수점 수(float, double)에서 발생

- 결과가 0에 가까워질 때 발생

ex) double result = 1e-300 * 1e-300;

여기서 1e-300은 1 ×10^(-300) -> 1 뒤에 소수점이 붙고, 그 뒤에 300개의 0이 오는 매우 작은 수

 

=> 표현 가능한 최솟값 미만의 값(너무 작은 값)을 0으로 처리할 때 언더플로우