[JAVA] 연산자(Operator) 정리

DongGyu Jung·2021년 12월 30일
0

자바(JAVA)

목록 보기
3/60
post-thumbnail

🏃‍♂️ 들어가기 앞서..

본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 Page : 〔투 비 마스터 : 자바〕

*해당 교재의 목차 순서와 구성 내용을 기준으로 작성하며
부족할 수 있는 내용은 추가적인 검색을 통해 채워나갈 예정입니다.



📕 연산자 (Operator)

연산을 수행하는 기호

  • 연산자(Operator) : 사칙연산 ( +, -, *, /) 를 비롯해서 다양한 연산을 수행하게끔 하는 기호

  • 피연산자(Operand) : 연산되어지는 연산의 대상 ( x + y에서 x 변수와 y변수)

  • 식(Expression) : 연산자와 피연산자를 조합하여 계산하고자 하는 바를 표현한 것

  • 평가(Evaluation) : 식을 계산하여 결과를 얻는 것

일반적으로 식이 평가되서 결과를 얻더라도 쓰이지 않으면 사라지기 때문에
연산자 중 대입 연산자(=) 을 사용해서 값을 저장한다.
(물론 평가결과만을 단순 출력할 목적이라면 출력 메서드(System.out.print() or System.out.println() 등 ) 에 직접 작성해도 된다.)

◎ 종류

종류연산자설명
산술 연산자+, -, *, /, %, <<, >>사칙연산과 나머지 연산
비교 연산자>, <, >=, <=, ==, !=크고 작음, 같고 다름을 비교
논리 연산자&&, ll , !, &, l, ^, ~AND(그리고) 와 OR(또는) 으로 조건 연결
대입 연산자=우변 값을 좌변에 저장
기타(type) ?: instanceof형변환 연산자, 삼항 연산자, instanceof 연산자
  • 피연산자 갯수로 연산자 분류 : (한 개) 단항 연산자, (두 개) 이항 연산자, (세 개) 삼항 연산자
    (보통 대부분의 연산자는 이항 연산자 이다.)

-3 -5라는 식을 한 번 살펴보자.
하나의 식으로 보기보단
우선적으로 각 피연산자의 위치와 부호의 개념으로 쪼개 살펴보는 것이 좋다.

얼핏 보면 두 -연산자가 모두 같아 보일 수 있지만
엄연히 서로 다른 이름의 연산자이다.

3 앞에 붙은 -는 <부호 연산자> 라고 불리우고
3과 5사이에 위치한 -는 산술 연산자 중 하나인 <뺄셈 연산자>라고 부른다.

'부호 연산자'는 단항 연산자로 피연산자가 3 한 개 뿐이고
'뺄셈 연산자'는 이항 연산자로 피연산자가 -35 두 개이다.

이처럼 연산자를 기능/피연산자의 개수 등을 기준으로 분류할 수 있는데
이러한 분류하는 이유를 설명하기 위해서는 연산자 우선순위를 빼놓을 수가 없다.

◎ 연산자 우선순위

" 식에 사용된 연산자가 둘 이상인 경우 "
이 연산자의 우선순위에 의해 연산되는 순서가 결정된다.

해당 부분은 정확히 기억은 나지않지만 초등/중등 교육과정에서 배웠던 바가 있을 것이다.

곱셈과 나눗셈을 덧셈과 뺄셈보다 우선적으로 연산 하는 부분이나
덧셈 뺄셈을 더 먼저하기 위해서 괄호를 통해 우선순위를 조작하는 등 말이다.

  • 단항 연산자 > 이항 연산자
  • 곱셈, 나눗셈 > 덧셈, 뺄셈
  • 산술 연산자 > 비교 연산자 > 논리 연산자 > 대입 연산자
    (대입연산자가 가장 마지막에 수행된다.)

◎ 연산자 결합 규칙

바로 위에서 연산자들간의 우선순위에 대해 알아보았는데
만약 " 식에 사용된 여러 연산자들의 우선순위가 같을 경우 "
이 경우에는 어떻게 할까?

당연히 아무거나 먼저 처리하는 것은 절대 아니다.
여기서 나름대로의 규칙이 존재하는데 이 규칙을
연산자의 결합 규칙이라고 한다.

먼저 유의해야 할 점을 먼저 언급하고 시작하겠다.
" 단항 연산자& 대입 연산자제외한 모든 연산의 방향은 왼쪽에서 오른쪽이다 "

예를 들어
3 + 4 - 5라는 식에서
+- 연산자는 우선순위가 같지만 단항연산자나 대입 연산자가 아니기 때문에
왼쪽에서 오른쪽으로 순차적인 연산을 진행한다.

x = y = 3이라는 식은 순서가 다르다.
위에 미리 언급했듯이
대입연산자이기 때문에 오른쪽에서부터 연산이 진행된다.
즉, y = 3이 먼저 수행되고
그 다음 x = 3으로 수행된다.


※ 증감 연산자

말 그대로 피연산자에 저장된 값을 1 증가혹은 1 감소시키는 연산자이다.
증감되는 값이 1로 정해져있기 때문에
이 연산자는 단항 연산자로 쓰이게 된다.

정수와 실수 모두 사용 가능하고
당연히 상수는 변경이 불가능하니 사용 불가능하다.
(자동 형변환은 발생하지 않고 연산결과의 타입은 피연사자의 타입과 동일하다.)

  • 증가 연산자 : ++ _ 피연산자 값 1 증가
  • 감소 연산자 : -- _ 피연산자 값 1 감소

기능은 얼핏 Python에서의 += 연산자나 -= 연산자와 유사하다 볼 수 있지만
전혀 다른 기능의 연산자이며
Java에서의 ++, -- (증감) 연산자와 큰 특징이 있다.

일반적으로 단항 연산자는 피연산자의 왼쪽에 위치하는데
증감연산자양 쪽 모두 가능하다.
<왼쪽>에 위치할 경우는 전위형(prefix), <오른쪽>에 위치할 경우는 후위형(postfix)이라고 한다.
차이는 " 값이 참조되기 전인가 후인가 "에 따라 분류된다.

  • 전위형(prefix) : 값이 참조되기 에 증가시킨다. (ex. J = ++i ;)
  • 후위형(postfix) : 값이 참조된 에 증가시킨다. (ex. J = i++ ;)
    (수식이나 메서드 호출에 포함되지 않으면 두 유형의 차이는 없다.)
int x, y;
x = 5 ;
y = 0 ;

y = x++;
System.out.println("(후위형) y = x++ ; 실행 후 x = " + x + ", y = " + y) ;
// (후위형) y = x++ ; 실행 후 x = 6, y = 5
// x=5 를 먼저 y에 대입한 다음, ++ (1 증가) _ y=x가 먼저 실행되고 ++이 후에 실행

x = 5 ;
y = 0 ;

y = ++x;
System.out.println("(전위형) y = ++x ; 실행 후 x = " + x + ", y = " + y) ;
// (전위형) y = ++x ; 실행 후 x = 6, y = 6
// ++x 를 먼저 y에 대입한 다음, x _굳이 나누자면 y=++가 먼저 실행되고 x가 후에 실행

아직 이게 무슨 말이지 싶을 수도 있다.
확실하게 이해하기 쉬운 예를 더 들어보겠다.

// 차이를 알아기 쉽게끔 x와 y를 동일한 값으로 설정
int x, y;
x = 5 ;
y = 5 ;

System.out.println(x++); // ++가 후에 실행되기 때문에 5
System.out.println(++y); // ++실행되고 y출력이 되기 때문에 6
System.out.println("x = " + x + ", y = " + y) ; // x++에서 현재는 ++도 실행됬기 때문에 6으로 출력됨
// x = 6, y = 6

※ 부호 연산자

이 연산자도 이미 여태까지 배워왔던 수학에서 질리도록 나왔던 내용인데
" 피연산자의 부호를 반대로 변경한 결과를 반환하는 기능 "이라고 설명할 수 있다.
(+ 부호연산자는 당연히 효용이 거의 없다.)

내가 다녔던 학교에서만 배운 노래일진 모르겠지만
쁠쁠 쁠 : +(+) : +
마쁠 마 : -(+) : -
쁠마 마 : +(-) : -
마마 쁠 : -(-) : +
이런 느낌의 노래가 있었다....

어쨋든 이 부호연산자 -
피연산자가 음수인 경우엔 양수
피연산자가 양수인 경우엔 음수로 변경하는 것이다.

단, boolean형과 char형에서는 사용할 수 없고
이 외의 기본형에서만 사용할 수 있다.

※ 형변환 연산자

서로 다른 타입 간의 연산을 수행해야 할 때,
타입을 일치시켜야 하는데 "변수"나 "리터럴"의 타입을 다른 타입으로 변환할 때 사용하는 연산자이다.

앞에 변환하고자 하는 타입을 괄호 안에 함께 붙여주기만 하면 된다.
(타입)피연산자 〕 형식

단, 꼭 알아둬야 할 점이 있는데
위와 같은 형식으로 변환한 값을 다른 변수에 저장할 때,
타입 변환 대상 피연산자의 값까지 형 변환되지 않는다.

double d = 85.4 ;
int score = (int) d; // 정수형으로 형 변환
System.out.println("score = " + score) ;
System.out.println("d = " + d) ;

/*
score = 85
d = 85.4	# 본래 값은 변하지 않는 것을 알 수 있다. _ 그저 읽어와서 새롭게 계산하는 것
*/

◎ 자동 형변환

물론 먼저 형변환으로 타입을 일치시킨 후, 대입과 연산을 하는 것이 원칙이긴 하나
때에 따라 생략할 수 있기도 하다.

아예 형변환을 안하고 연산되는 것이 아니고
컴파일러가 생략된 형변환을 자동적으로 추가한 다음 연산을 처리한다.

단, 모든 경우가 생략이 가능한 것이 아니다.
만약 가능하다면 이 자동 형변환에 대해 알 필요가 없을 것이다.

이 부분에서 상당히 중요한 부분은 이전 글에서 공부했던 자료형 크기이다.
변수가 저장할 수 있는 값의 범위보다
더 큰 값을 저장
하려는 경우
에러가 발생한다.
(incompatible types: possible lossy conversion from (type) to (type) = 큰 타입에서 작은 타입으로의 형변환은 값 손실이 발생할 수 있다는 뜻)

물론 더 큰 값을 저장하는 것이 아예 불가능한 것은 아니고
이 때 명시적으로 형변환을 해주면
값의 손실은 발생하지만 에러를 발생시키진 않는다

정리하자면

자동 형변환은 기존 값을 최대한 보존할 수 있는 타입으로 변환된다.
(기존 값 보존이 우선적인 조건이기 때문에 명시하지 않는 이상 에러가 발생한다.)

  • 저장범위가 좁은 타입넓은 타입 : 값 손실이 없기 때문에 두 type 중 더 넓은 쪽으로 자동 형변환
  • 넓은 타입좁은 타입 : 값 손실이 발생하기 때문에 반드시 형변환 연산자 사용해야 가능

※ 사칙 연산자

가장 많이 사용되는 연산자일텐데
그 중에서 덧셈(+), 뺄셈(-), 곱셈(*), 나눗셈(/) 이 4가지가 가장 많이 쓰일 것이다.

사용하는데에 있어
앞서 설명했던 우선 순위를 잘 고려해서 식을 작성해서 사용하면 되며

주의할 점으로는
피연산자가 정수형일 때,
나눗셈 식에서 나누는 수0을 사용하면 에러가 발생한다.

또한,
피연산자가 모두 int형이라고 할 때,
나눗셈을 했는데 나머지가 나오더라도 나머지를 버린 정수 값만 결과로 출력된다. ( 반올림 X )
그렇기 때문에 올바른 계산을 위해서는
두 피연산자 중 어느 한 쪽
int 타입보다 범위가 넓은 float타입으로 일치시킨 후에
연산을 수행시켜야 한다.

int a = 5 ;
int b = 2 ;

System.out.printf("%d + %d = %d %n", a, b, a+b) ;
System.out.printf("%d - %d = %d %n", a, b, a-b) ;
System.out.printf("%d * %d = %d %n", a, b, a*b) ;
System.out.printf("%d / %d = %d %n", a, b, a/b) ; // 나머지가 버려지고 정수부분만 출력
System.out.printf("%d / %f = %f %n", a, (float)b, a/(float)b) ; // 둘 중 한 쪽이라도 형변환하면 가능해짐.
System.out.printf("%f / %d = %f %n", (float)a, b, (float)a/b) ;

/*
5 + 2 = 7 
5 - 2 = 3 
5 * 2 = 10 
5 / 2 = 2 
5 / 2.000000 = 2.500000 
5.000000 / 2 = 2.500000 
*/

◎ 산술 변환

( a.k.a 일반 산술 변환 )

위에서 알아봤던 자동 형변환은 단순히
대입의 경우에서만 살펴보았는데

이번에 살펴볼 산술 변환
산술 연산 시, 피연산자 타입의 일치를 위해 자동 형변환되는 것을 말한다.

✔ 산술 변환 규칙

<최소의 기준이 int타입이라고 생각하면 쉽다.>
위에서 살펴봤던 예시를 참고해도 이해하기 편할 것이다.

① 두 피연산자 타입 일치 (비교했을 때 보다 큰 타입으로)

  • long + int ▶ long + long → long
  • float + int ▶ float + float → float
  • double + float ▶ double + double → double

② 만약 피연산자 타입이 int보다 작은 타입이면 int 타입으로 변환

  • byte + short ▶ int + int → int
  • char + short ▶ int + int → int
byte a = 10;
byte b = 20;
/*
a와 b가 byte형으로 int보다 작기 때문에
산술하게되면 자동으로 int형으로 산술변환 되기때문에
저장되는 변수가 int타입이거나 더 넓은 범위여야 함.
byte c = a + b ; 는 incompatible types: possible lossy conversion from int to byte 에러
*/
int c = a + b; //정상적인 값 저장
int d = a * b;
System.out.println(c) ;
System.out.println(d) ;

//강제 형변환 해주었을 때는 '손실'발생
byte e = (byte)(a+b) ;
byte f = (byte)(a*b) ;

System.out.println(e) ; // byte 범위 내의 값이기 때문에 손실은 발생하지 않음 _ (byte) 강제 형변환되면 산술연산 가능
System.out.println(f) ; // -56 _ 연산은 가능해졌지만 데이터 손실 발생

이번엔 " 결과값이 int의 범위보다 넓을 경우 "에 대해 알아보자.
위에서 설명했듯이
기본적으로 정수 계산시, 결과 또한 int타입으로 자동 형변환이 되는데
만약 결과 값이 약 20억을 훨씬 넘는 값이라면
int 타입이 담기엔 부족한 값이다.

그렇게 되면 당연히 에러가 나기 때문에
이러한 경우에는 int타입보다 범위가 넓은 long타입으로 형변환 시켜주어야 한다.

int a = 1_000_000 ; // 1백만
int b = 2_000_000 ; // 2백만
/*
a와 b의 곱은 2,000,000,000,000으로 2조 라는 값이 나온다.
int의 범위인 양/음수 약 20억 범위보다 훨씬 큰 값이기 때문에
결과값의 타입은 int가 아닌 long이 되어야 한다.

담으려는 변수는 long일지라도
산술변환 특성상
정수 연산을 하게되면 대입하려한 연산결과의 타입은 int형이 되기 때문에

대입되는 것까지도 에러 발생되지 않지만
평가결과 타입이 맞지않아 손실된 채로 저장된다.
*/
long c = a * b ; // 담기긴 하지만 손실된 데이터임
long d = (long)a * b ; // long + int로 int는 자동으로 long으로 변환되서 연산됨.

System.out.println(c) ; // -1454759936
System.out.println(d) ; // 2000000000000

바로 위의 모습처럼 작성해도되지만

처음부터 피연산자로 쓰일 변수 자체를 long타입으로 선언하고 사용하거나
피연산자로 변수를 사용하지 말고 직접 long타입 값을 사용하는 것이
더 편리한 방법이 될 수도 있다.
(ex. long a = 1_000_000L ; long b = 2_000_000 or long c = 1_000_000L * 2_000_000L )

◎ 반올림 [ Math.round() ]

Math.round() 메서드를 사용할 때 주의할 점이 있다.
이 메서드는 소수점 첫째 자리에서 반올림한 결과를 정수로 반환하기 때문에
첫째자리가 아닌 다른 자리에서 반올림한 결과를 얻고싶다면
10^n으로 적절히 곱하고 나누는 작업이 필요하다.

아!
그리고 일반 산술변환도 주의해야한다.
자릿수를 맞추기위해 나눌 값을 작성할 때,
정수 int타입으로 10^n을 사용하면 결과값은 당연히 float타입이 아닌 int타입이다.
(뒤에 .0 붙이는 것 잊지말자!)

double pi = 3.141592;
double intpi = Math.round(pi * 1000) / 1000 ; // .0 없이 int타입 1000을 나눴을 때 
double roundpi =  Math.round(pi * 1000) / 1000.0 ;

System.out.println(intpi) ; // 3.0
System.out.println(roundpi) ; // 3.142

◎ 나머지 연산자 ( % )

특별히 크게 설명할 부분은 없다.
말 그대로 나머지를 구하는 연산자인데

한 가짗 짚을 것이라고 한다면
나누는 수음수도 허용한다는 점인데
부호는 무시되므로 결과는 절댓값으로 나눈 나머지와 결과가 같다.

※ 비교 연산자

주로 조건문반복문에서 자주 쓰이는
두 피연산자를 비교하는데 사용되는 연산자이다.
결과는 오직 truefalse 둘 중 하나이다.
(기능은 아마 다들 어느정도 배웠기때문에 어렵지 않을 것이다)

이 연산자 또한 이항 연산자이기 때문에
피연산자의 타입이 서로 다를 경우,
범위가 큰 쪽으로 자동 형변환하여 타입을 일치시킨 후, 비교한다는 점 명심해야한다.

◎ 대소 비교

> , <, >=, <= : >나 <는 무조건 좌측에 위치해야 한다.

  • 기본형 : boolean 제외한 나머지 자료형 모두 사용 가능
  • 참조형 : 사용불가

◎ 등가 비교

== , !=

  • 기본형 : 사용 가능 _ " 변수에 저장된 값이 같은지 "

  • 참조형 : 사용 가능 _ " 같은 객체를 가르키고 있는지 (주소값 같은지) "

    기본형과 참조형은 서로 형변환이 불가능하기 때문에 서로 비교할 수 없다.

◎ 문자열(String) 비교

두 문자열을 비교할 때는,
비교연산자 ==이 아닌 equals()을 사용해야 한다.
== 연산자는 두 문자열이 모든 비교 사항이 완전히 같은지를 비교하는 것이기 때문에
equals() 메서드를 사용하는 것이 내용이 같은지 비교할 때 용이하다.

String str1 = "abc" ; //

boolean result = str1.equals("abc") ; //true
System.out.println(result) ;
System.out.println(str1 == "abc") ; // true

String str2 = new String("abc") ; // str1과 ==연산자 차이점을 만들기 위해 다른'객체'로 생성 _ 내용은 같으나 다른 객체 (주소값 다름)

System.out.printf("\"abc\" == \"abc\" 는 %b %n", "abc"=="abc") ; // ""를 문자열로 사용할 땐 \" 의 형식으로 작성해야함.
System.out.printf("str1 == \"abc\" 는 %b %n", str1=="abc") ;
System.out.printf("str2 == \"abc\" 는 %b %n", str2=="abc") ; // 다른 객체이기 때문에 false 출력
System.out.printf("str1.equals(\"abc\") 는 %b %n", str1.equals("abc")) ;
System.out.printf("str2.equals(\"abc\") 는 %b %n", str2.equals("abc")) ;
System.out.printf("str2.equals(\"ABC\") 는 %b %n", str2.equals("ABC")) ;
// equalsIgnoreCase 는 대소문자 구분 X
System.out.printf("str2.equalsIgnoreCase(\"ABC\") 는 %b %n", str2.equalsIgnoreCase("ABC")) ;

/*
"abc" == "abc" 는 true 
str1 == "abc" 는 true 
str2 == "abc" 는 false 
str1.equals("abc") 는 true 
str2.equals("abc") 는 true 
str2.equals("ABC") 는 false 
str2.equalsIgnoreCase("ABC") 는 true 
*/

※ 논리 연산자

&&(그리고_AND) , ||(혹은_OR)

둘 이상의 조건을 연결하여 하나의 식으로 표현할 수 있게 해주는 연산자이다.
연산자들 중에서 대입 연산자 다음으로 우선순위가 낮은 연산자인데
덧셈, 뺄셈의 경우 괄호로 감싸 별도 연산할 수 있게 하는데
이 논리 연산자 또한 당연히 괄호를 통해 중첩해서 이중 논리 연산이 가능하다.
주어진 조건이 " x는 2의 배수 또는 3의 배수이지만 6의 배수는 아니다. "이라면
(x%2 == 0 || i%3 == 0) && i%6 != 0 형식으로 이중이면서 분리해서 두 가지 이상의 조건을 걸 수 있다.

우선 논리 연산자도 truefalse 두가지 결과만 출력하고
비교연산 결과에 대한 연산을 처리하기 때문에
좌항과 우항의 위치는 크게 상관이 없다

예를 들어
" x는 10보다 크고 20보다 작다. "라는 조건을 표현하면
x > 10 && x < 2010 < x && x < 20 두 형식으로 모두 표현 가능하다.

또한
문자를 비교할 때 유니코드(숫자)를 활용할 수 있는데
만약 숫자문자('0'~'9')인지 확인한다고 할 때
해당 숫자문자의 코드 범위인 48('0')~57('9')을 숫자 대소비교와 논리 연산으로
식을 작성할 수 있다.
'0' <= chr && chr <= '9' 식으로 작성할 수 있는데
해석하면 48 <= chr && chr <= 57과 같다.

이 유니코드를 활용해서 입력된 문자가 대문자인지 소문자인지 확인하는 것도 가능하다.

Scanner scanner = new Scanner(System.in) ; //입력받기
char chr = ' '; //빈 char

System.out.printf("문자를 하나 입력하시오. >> ") ;

String input = scanner.nextLine();
chr = input.charAt(0) ;

if ('0' <= chr && chr <= '9') {
    System.out.printf("입력하신 문자는 숫자입니다.");
}
if (('a' <= chr && chr <= 'z') || ('A' <= chr && chr <= 'Z')) {
    System.out.printf("입력하신 문자는 영문자입니다.") ;
}
else {
    System.out.printf("입력하신 문자는 영문자나 숫자가 아닙니다.");
}

◎ 논리 부정 연산자

말 그대로 피연산자의 논리값을 부정하는 연산자로
!(느낌표)를 사용하며
기능은 true → false나 false → true식으로 바꾸는 것이다.

독특하게도 이 ! 기호를 여러 개를 사용할 수도 있고
(연산 순서는 피연산자와 가까운 것부터 먼저 연산된다.)

!기호를 썼다 지웠다를 반복하며
조건문 등에서 이분법적인 수행결과를 의도할 수 있다.
(ex. <false_거짓_Off><true_참_On><false_거짓_On><true_참_On> 등)

boolean i = true ;

System.out.printf("i = %b %n", i) ; // true
System.out.printf("!i = %b %n", !i) ; // false
System.out.printf("!!i = %b %n", !!i) ; // true
System.out.printf("!!!i = %b %n", !!!i) ; // false
System.out.println() ;

char chr = 'A' ;// 대문자

System.out.printf("chr = %c %n", chr) ; // ""를 문자열로 사용할 땐 \" 의 형식으로 작성해야함.
System.out.printf("chr < 'a' || chr > 'z' = %b %n", chr < 'a' || chr > 'z') ;
System.out.printf("!('a' <= chr && chr <= 'z') = %b %n", !('a' <= chr && chr <= 'z')) ;
System.out.printf("'a' <= chr && chr <= 'z' = %b %n", 'a' <= chr && chr <= 'z') ;

/*
i = true 
!i = false 
!!i = true 
!!!i = false 

chr = A 
chr < 'a' || chr > 'z' = true _ a~z만 제외한 값들 중에 대문자가 있음 (a보다 z가 크기 때문에 구간 제외시키는 식) 

!('a' <= chr && chr <= 'z') = true 
'a' <= chr && chr <= 'z' = false  !로 위 식과 반대
*/

※ 조건 연산자

이 연산자는 상당히 생소한 연산자였는데
조건식을 먼저 작성하고
이 조건식의 참/거짓에 따라 : 기호 기준으로
좌측 식 / 우측 식을 연산하게 끔하는 연산자이다.
(조건 연산자 또한 위 다른 연산자들과 마찬가지로 중첩이 가능하다)

( 조건식 ) ? (식1) : (식2)

  • 조건식이 일 때 : 식 1을 연산
  • 조건식이 거짓일 때 : 식 2를 연산

기능은 if 조건문을 사용할 때와 유사하다.
위 식을 if문으로 풀어보면

//조건 연산자 사용
result = (x>y) ? x : y

//IF 조건문 사용
if (x>y)
  result = x;
else 
  result = y;

또 신기한 것은
일반 식의 일부분에만 위와 같이 조건 연산자를 활용할 수 있다.

/*
상단엔 x변수 선언과 mod 변수의 값이 주어진 상태
*/

x = x + (mod < 0.5 ? 0 : 0.5) // 조건 연산자의 두 피연산자 (0, 0.5)의 타입이 다른 경우

위와 같은 식이 연산되게 되면
피연산자의 타입에게 자동 형변환이 일어나 두 피연산자 모두 double타입으로 통일되어 연산된다.

x = x + (mod < 0.5 ? 0.0 : 0.5)

그 결과 해당 x에 대입될 땐 double 타입 값이 대입된다.


※ 대입 연산자

연산자들 가운데 가장 낮은 우선순위를 가진 연산자로
우측 피연산자 값을 좌측 피연산자에 저장/대입하는 기능을 갖는다.

반환하는 값은 좌측 피연산자( 저장된 값 )를 반환한다.

앞서 설명했듯 연산 진행방향은
오른쪽 → 왼쪽이기 때문에 이 점을 주의해야 한다.

  • 좌측 피연산자 : lvalue _ 값을 변경/저장할 수 있는 것 ( 변수 등 )
  • 우측 피연산자 : rvalue _ 변수, 식, 상수 등 모두 가능
int i = 0
3 = i + 3 ; // 에러 : lvalue가 변경가능한 값이 아니다.
i + 3 = i ; // 에러 : lvalue의 연산결과가 리터럴이다.

final int Ten = 10;
Ten = 11 ; // 에러 : lvalue는 상수(constant)이기 때문에 새로운 값 저장 불가

◎ 복합 대입 연산자

다른 연산자와 결합하여 (operator)=의 형식으로 사용할 수있다.
이 복합 대입 연산자 중 하나를 Python에서도 많이 볼 수 있었는데
바로 +=-=연산자들이 이 복합 대입 연산자이다.

주의해야할 점은 계산 순서라고 해야할까
우변에는 하나의 식이 들어갈 수 있는데
복합 대입 연산자는 우선수위 낮다는 점을 잊어선 안된다.

먼저 예시를 들어보겠다.

형식연산 방식
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)

위에서 언급한 주의할 점은 위 표의 마지막 줄 부분이라고 생각하면 된다.

0개의 댓글