[Java] 연산자

2022. 8. 9. 21:37BE/Java

프로그램에서 데이터를 처리하여 결과를 산출하는 것연산이라 한다.

연산에 사용되는 표시나 기호연산자라 하고 연산되는 데이터피연산자라고 한다.

연산자와 피연산자를 이용하여 연산의 과정을 기술한 것을 연산식이라고 부른다.

x + y
x - y
x * y + z
x == y

 

연산자는 필요로 하는 피연산자 수에 따라 단항, 이항, 삼항 연산자로 구분된다.

연산식은 반드시 하나의 값을 산출한다.

 

연산의 방향

대부분의 연산자는 왼쪽에서 오른쪽으로 연산을 시작한다.

증감(++, --), 부호(+, -), 비트(~), 논리(!), 대입 연산의 경우 오른쪽에서 왼쪽으로 연산한다.

 

연산 우선순위

일차식 ( ), [ ]

증감 (++, --), 부호(+, -), 비트 반전(~), 논리(!)

산술 (*, /, %)

산술 (+, -)

쉬프트 (<<, >>, >>>)

비교 (<, >, <=, >=, instanceof)

비교 (==, !=)

비트 곱 (&)

비트 차 (^)

비트 합 (|)

논리 곱 (&&)

논리 합 (||)

조건 ? :

대입 (=, +=, -=, *=, /=, %=, &=, ^=, |=, <<=, >>=, >>>=)

 

※ 단항, 이항, 삼항 연산자 순으로 우선순위를 가진다.

 

단항 연산자

피연산자 하나뿐인 연산자

부호 연산자

양수, 음수를 표시하는 +, -를 말한다.

boolean 타입과 char 타입을 제외한 나머지 기본 타입에 사용할 수 있다.

int i = +100;
doublie d1= -10.5;

부호 연산자의 산출 타입은 int 타입이 된다.

short s = 100;
short result = -s; // 컴파일 에러

증감 연산자

변수 값을 1 증가 또는 1 감소시키는 연산자

boolean 타입을 제외한 모든 기본 타입 피연산자에 사용할 수 있다.

 

증감 연산자와 피연산자 위치에 따라 의미가 연산 순서가 다르다.

i ++ → 다른 연산 수행 후 i 값 1 증가

++ i → 다른 연산 수행 전에 i 값 1 증가

 

※ ++i 가 i = i + 1 보다 연산 속도가 빠르다.

전자는 연산자가 하나이고 후자는 연산자가 두 개이기 때문에 연산이 더 많이 필요하다.

그러나 컴파일을 하면 동일한 바이트 코드가 생성된다.

논리 부정 연산자

! 인 연산자를 말한다.

true를 false로, false를 true로 변경하여 boolean 타입에만 사용할 수 있다.

비트 반전 연산자

~ 인 연산자를 말한다.

정수타입 (byte, short, int, long)의 피연산자에만 사용가능하다.

피연산자를 2진수로 표현했을 때 비트 값인 0을 1로, 1을 0으로 반전한다.

부호 비트인 MSB를 포함해서 모든 비트가 반전된다.

피연산자는 연산 수행 전에 int 타입으로 변환되고 비트 반전이 일어난다.

byte b1 = 10;
byte b2 = ~b1; // 컴파일 에러

비트 반전 연산은 1의 보수를 의미하므로 여기에 1을 더하면 2의 보수이므로

부호를 바뀐 값을 산출할 수 있다.

byte b1 = 10;
int b2 = ~b1 + 1; // 2의 보수 취함 (-10)

 

이항 연산자

피연산자가 두 개인 연산자

산술 연산자

사칙연산에 사용되는 연산자

boolean 타입을 제외한 모든 기본 타입에서 사용할 수 있다.

+, -, *, / : 덧셈, 뺄셈, 곱셈, 나눗셈

% : 나머지 연산

 

산술 연산자 특징은 피연산자들의 타입이 동일하지 않은 경우 통일시킨 후 연산을 수행한다.

1. 피연산자들이 모두 정수 타입이고, int 타입보다 크기가 작은 경우 모두 int 타입으로 변환 후 연산 수행

2. 피연산자들이 모두 정수 타입이고, long 타입이 있을 경우 모두 long 타입으로 변환 후 연산 수행

3. 피연산자 중 실수 타입이 있을 경우, 크기가 큰 실수 타입으로 변환 후 연산 수행

byte b1 = 10;
byte b2 = 20;
byte result = b1 + b2; // 컴파일 에러

정수 타입 연산 결과가 int 타입으로 나오는 이유는 JVM이 기본적으로 32비트 단위로 계산하기 때문이다.

int i1 = 10;
int i2 = 4;
int result1 = i1 / i2; // 2
double result2 = i1 / i2; // 2.0 (연산의 결과는 int 타입간 연산이므로 연산 결과는 int)

char 타입도 정수 타입이므로 산술 연산이 가능하다.

char c1 = 'A' + 1; // 66
char c2 = 'A'; // 65
char c3 = c1 + c2; // 컴파일에러, 산출타입은 int형이기 때문에

 

※ 오버플로우 탐지

산술 연산 할 때 산출값이 산출 타입으로 충분히 표현 가능한지 살펴봐야한다.

오버플로우 탐지하는 메소드 구현

산술 연산자를 사용하기보다는 오버플로우 예외 처리된 메소드를 사용하는 것이 좋다.

 

※ 정확한 계산은 정수 사용하기

정확하게 계산해야 할 때 부동소수점(실수) 타입을 사용하지 않는 것이 좋다.

실수 타입으로 계산
계산 결과 0.3이 안 나온다.

정확히 0.3이 나오지 않는다.

float, double 부동 소수점 타입은 0.1을 정확히 표현할 수 없어 근사치로 처리하기 때문이다.

 

정수 연산으로 변경해서 연산 수행

정수 타입으로 변경하여 계산하는게 정확한 값을 출력할 수 있다.

 

※ NaN과 Infinity 연산

/ 또는 % 연산자 사용 시 주의할 점은 피연산자가 모두 정수일 때 좌측 연산자가 0이면 ArithmeticException 예외가 발생한다.

연산자에 실수 타입이 포함된 경우 0으로 나누면 Infinity

0으로 나눈 나머지는 NaN 이 산출된다.

Infinity와 NaN는 연산 결과는 모두 자기 자신이 되어 연산 결과가 제대로 나오지 않는다.

연산 결과가 Infinity 또는 NaN인지 확인하려면 Double.isInfinite()와 Double.isNaN() 메소드를 사용하면 된다.

 

※ 입력값의 NaN 검사

실수를 입력 받을 때 반드시 NaN 검사를 해야한다.

부동소수점으로 변환 가능한 문자열을 입력 받을 때 NaN 입력할 수 있다.

NaN은 산술 연산이 가능하나 모든 결과가 NaN이 나온다.

NaN인지 확인할 때 == 연산자를 사용하면 안된다.

!= 를 제외한 모든 비교 연산 결과로 false를 리턴한다.

 

문자열 연결 연산자

문자열을 연결할 때 사용하는 + 연산자

 

※  피연산자에 정수와 문자열이 있으면 두 피연산자를 문자열로 취급하고 문자열 연결 연산을 수행한다.

 

비교 연산자

<, <=, >, >=, ==, != 인 연산자다.

boolean 타입으로 산출한다.

대소 연산자는 boolean 타입을 제외한 기본 타입에 사용할 수 있다.

동등 연산자는 모든 기본 타입에 사용할 수 있다.

 

피연산자가 char 타입이면 유니코드 값으로 비교 연산을 수행한다.

피연산자간 타입이 다른 경우 큰 타입으로 변환하고 비교한다.

 

0.1 == 0.1f 는 결과가 false가 나온다.

이진 포맷 가수를 사용하는 모든 부동소수점 타입은 0.1을 정확히 표현할 수 없어 0.1f가 double로 변환되면서 값이 바뀐다. 그래서 0.1과 같은 값이 아니다. (0.1보다 조금 더 큰 값)

 

String 문자열을 비교할 때 == 연산자를 사용하지 않는다.

문자열만 비교하는 equals() 메소드를 사용해야 한다.

※ String은 참조 타입이기 때문에 == 연산을 할 경우 주소값이 같은지 비교하게 된다.

 

문자열 비교는 equals 메소드 사용

문자열 리터럴이 동일하면 동일한 주소값을 가진다.

new 로 새로운 객체를 만들면 새로운 주소를 참조하기 때문에 문자열이 같더라도 == 연산에서는 false를 산출한다.

 

논리 연산자

&&, ||, &, |, ^, ! 인 연산자

boolean 타입인 피연산자에 대해서만 사용할 수 있다.

&& 또는 & : 피연산자 모두 true이면 true

|| 또는 | : 피연산자 중 하나 이상 true이면 true

^ : 피연산자 값이 서로 다르면 true

! : 피연산자 값 반전

 

※ &&와 &는 산출 결과는 같지만 연산 과정이 다르다.

&&는 앞의 피연산자가 false라면 뒤의 피연산자를 평가하지 않고 바로 false라는 산출 결과를 낸다.

그러나 &는 두 피연산자를 모두 평가해서 산출 결과를 낸다.

||과 |도 마찬가지다.

 

비트 연산자

&, |, ^, ~.<<,>>,>>> 인 연산자

비트 연산자는 데이터를 비트 단위로 연산한다.

0과 1로 표현이 가능한 정수 타입만 비트 연산을 할 수 있다.

float, double 은 비트 연산을 할 수 없다.

비트연산자는 피연산자를 int 타입으로 변환 후 연산을 수행한다.

 

비트 논리 연산

& : 비트곱 (두 비트 모두 1이면 1)

| : 비트합 (두 비트 중 하나 이상 1이면 1)

^ : 비트차 (두 비트 다르면 1)

~ : 비트 반전 (1의 보수)  ← 단항 연산자

 

비트 이동 연산

정수 데이터 비트를 좌측이나 우측으로 밀어서 이동시키는 연산이다.

a << b : 정수 a를 b만큼 왼쪽으로 이동 (빈자리는 0으로 채워진다.)

a >> b : 정수 a를 b만큼 오른쪽으로 이동 (빈자리는 MSB 값으로 채워진다.)

a >>> b : 정수 a를 b만큼 오른쪽으로 이동 (빈자리는 0으로 채워진다.) 

비트 연산 결과는 int 타입

 

대입 연산자

=, +=, -=, *=, /=, %=, &=, ^=, |=, <<=, >>=, >>>= 인 연산자

대입 연산자는 몯느 연산자들 중에서 가장 낮은 연산 순위를 가지고 있다.

오른쪽에서 왼쪽으로 연산 순서를 가진다.

 

삼항 연산자

조건식 ? True면 이거 : False면 이거

피연산자에 값이 올수도 있고 연산식이 올 수도 있다.

 

728x90

'BE > Java' 카테고리의 다른 글

[Java] 반복문  (0) 2022.08.27
[Java] 조건문  (0) 2022.08.27
[Java] 데이터 타입  (0) 2022.08.05
[Java] 변수  (0) 2022.08.04
[Java] 이클립스 설치  (0) 2022.08.04