연산자

Jaca·2021년 8월 12일
0

연산자란

연산을 수행하는 기호

연산자와 피연산자

연산자가 연산을 수행하려면 연산의 대상이 있어야한다.
이것이 피연산자, 피연산자는 상수, 변수, 식 등을 사용할 수 있다.

연산자의 종류

종류연산자설명
산술 연산자+, -, *, /, %, <<, >>사칙 연산과 나머지 연산
비교 연산자>, <, >=, <=, ==, !=크고 작음과 같고 다름을 비교
논리 연산자&&, ||, !, &, |, ^, ~AND와 OR로 조건을 연결
대입 연산자=우변의 값을 좌변에 저장
기타(type), ?:, instanceof형변환 연산자, 삼항 연산자, instanceof 연산자

연산자의 우선순위와 결합규칙

종류결합 규칙연산자우선순위
단항 연산자<--++, --, +, -, ~, !, (type)가장 높음
산술 연산자-->*, /, %
비교 연산자--><, >, <=, >=, instanceof
논리 연산자-->&|
논리 연산자-->^
논리 연산자-->
논리 연산자-->&&
논리 연산자-->||
삼항 연산자-->?:
대입 연산자<--=, +=.. 등등가장 낮음

1. 산술 > 비교 > 논리 > 대입. 대입은 제일 마지막
2. 단항(1) > 이항(2) > 삼항(3) 항이 많을 수록 우선순위가 낮다
3. 단항 연산자와 대입 연산자를 제외한 모든 연산의 진행 방향은 -->

특징

byte + byte = int?

byte a = 10;
byte b = 20;
byte c = a + b;

위 코드는 에러가 난다. (int)(a + b)로 캐스팅 해주라는 에러를 만날 수 있다.
이유는 자바에서 int보다 작은 자료형의 산술연산은 int가 기본 값이다.

char + int?

char c1 = 'a';
//char c2 = c1 + 1;
char c2 = (char) c1 + 1; // b
char c3 = 'a' + 1; // b
c3++; // c

2행은 에러를 발생시킨다.
2행과 3행의 차이는 무엇일까?
c1 + 1 이라는 연산은 c1이 char형이므로 int형으로 변환한 후 덧셈연산을 수행하게 되고, 이는 int + int = int의 결과를 얻는 것이다.

하지만 그렇다면 4행은 왜 에러를 발생하지 않는 걸까?
이유는 'a' + 1이 리터럴 간의 연산이기 때문이다.
상수 또는 리터럴 간의 연산은 실행 과정동안 변하는 값이 아니기 때문에, 컴파일 시에 컴파일러가 계산해서 그 결과로 대체함으로써, char 3= 'b' 의 식으로 대체된다.

결과적으로 3행과 4행의 가장 큰 차이는 변수인 c1 과 상수인 'a' 의 차이이다.

실수형, 소수점 다루기

//소수 셋째 자리 이하 버리기
float pi = 3.141592f;
float shortPi = (int)(pi * 1000) / 1000f; // 3.141

//흐름
(int)(pi * 1000) / 1000f;
(int)(3141.592f) / 1000f;
3141 / 1000f; // 3141은 inf형이라 곱셈시 소수점이 버려짐
3.141f

//버림이 아닌 반올림 하기
shortPi = (int)(pi * 1000 + 0.5) / 1000f; // 3.142f

//흐름
(int)(pi * 1000 + 0.5) / 1000f;
(int)(3141.592f + 0.5) / 1000f;
(int)(3142.092f) / 1000f;
3142 / 1000f;
3.142

Math.round(pi * 1000) 으로 대체 가능

실수와의 비교연산자

10 == 10.f 를 비교 할 때 결과는 true를 받게 된 다.
비교연산자 또한 양 쪽의 자료형을 맞춰주기 위해 10을 float형으로 변환하여 비교한다.

float f = 0.1f;
double d = 0.1;
double d2 = (double)f;

10.0 == 10.0f; // true
0.1 == 0.1f // false;
f = 0.10000000149011612;
d = 0.10000000000000000;
d2 = 0.10000000149011612;

d == f; // false
d == d2; // false
d2 == f; // true
(float)d == f; // true

위의 결과는 어떻게 된것일까?
똑같은 0.1 이지만 float와 double의 값이 다른 것을 볼 수 있다.
10.0f는 오차없이 저장할 수 있는 값이라 double형으로 변환해도 오차가 없다.

하지만 0.1f는 저장할 때 2진수로 변환하는 과정에서 오차가 발생한다.
double 타입의 상수인 1.0 도 오차가 발생하지만, float보다 적은 오차가 발생해서 값이 달라지는 것이다.

또 float를 double로 형변환한다고 해도 가수의 빈자리를 0으로 채울 뿐이라 오차가 적어지진 않는다.
그래서 d2와 f가 같은 것이다.

double을 float로 형변환하면 어느정도의 오차를 무시하고 두 타입의 값을 앞에서 몇 자리만 잘라서 비교해서 올바른 결과를 얻을 수 있다.

문자열의 비교

일전의 내용에서 String은 클래스 형이라 새로운 객체를 생성하는 것이라고 배웠다.

String str = new String("abc");

처럼 생성해야 하는 객체를 편의를 위해

String str = "abc"; 처럼 편의를 위해 간단히 표현하는 것이다.

그래서 String을 == 연산자로 비교하게 되면 같은 내용이지만 다른 객체 이기 때문에 false를 얻게 된다.

이를 위해 String은 equals() 메소드를 이용해야 한다.

논리 연산자의 효율적인 연산

xyx||y
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse

OR 연산의 테이블 표 이다.
논리 연산자의 특징은 효율적인 연산을 한다.
알다시피 두 피연산자중 한 피연산자만 true이면 true의 결과를 얻는다.
두 피연산자 중 한 피연산자가 true면 전체 연산 결과가 true이기 때문에, 좌측 피연산자가 true이면 우측 피연산자의 값은 평가하지 않는다.

xyx&&y
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse

AND 연산은 반대로
좌측 피연산자가 false라면 우측 피연산자의 값은 평가하지 않는다.

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

비트 연산자

비트 연산자는 아직 비트 마스킹과 관련하여 지식이 부족하기 때문에,
조만간 알고리즘 파트에서 한번에 정리하리라..!

profile
I am me

0개의 댓글