연산자
: 연산에 사용되는 표시나 기호
피연산자
: 연산되는 데이터
단, 연산결과를 반환하지 않으면 연산자가 아니다.
괄호 ( )를 사용해서 우선 연산 가능
일반적인 연산자
: 왼쪽 → 오른쪽 방향으로 연산
단항 연산자
, 대입 연산자
: 왼쪽 ← 오른쪽 방향으로 연산
// 예시
class Main {
public static void main(String[] args) {
int x, y;
x = y = 3; // y 에 3 저장된 후, x에 3 저장됨
System.out.println(...);
}
}
2 순위
byte b = 100;
byte result = -b // 컴파일 에러
int result = -b
char타입(정수), boolean타입(논리)을 제외하고 모두 사용 가능
연산 결과는 int 타입(정수)
1순위
int x = 1;
int y = 1;
int result1 = ++x + 10; // x + 1 = 2 + 10 = 12
int result2 = y++ + 10; // y + 10 = 11, y = 2
boolean타입(논리)을 제외하고 모두 사용 가능
++i 와 i++ 은 연산 속도 차이 X
x++, ++x 구분 필요!
Q. 다음 코드를 실행했을 때 출력 결과는 무엇입니까?
int x = 10;
int y = 20;
int z = (++x) + (y--);
System.out.println(z);
A. 출력 결과 : 31
++X 에서 증가 연산자 ++은 다른 연산을 수행하기 전에, 피연산자 x의 값을 1 증가시킨다.
y--에서 감소 연산자 --는 다른 연산을 수행한 후에, 피연산자 y의 값을 1 감소시킨다.
따라서, int z = (1+10) + (20) = 31이 저장된다.
그 이후에, y는 감소 연산을 수행하여 19가 된다.
1 순위
boolean play = true;
System.out.println(play);
play = !play;
System.out.println(play);
play = !play;
System.out.println(play); // false를 부정
/* 실행결과
true
false
true */
boolean타입(논리)만 사용 가능
→ true/false 가 서로 변경됨
조건문, 제어문에서 사용 : 조건식의 값 부정하도록 해서
토글 기능 구현에 사용 : 두 가지 상태(true/false) 번갈아 번경해서
2 순위
double result3 = (int1 * 1.0) / int2;
double result3 = (double) int1 / int2;
double result3 = int1 / (dobule) int2;
피연산자 타입을 동일하게 만든다
2.5 산출하는 법
Q. 다음 코드를 실행하면 출력 결과로 5를 기대했는데 4가 출력되었습니다. 어디에서 잘못 작성된 것일까요?
int var1 = 5;
int var2 = 2;
double var3 = var1 / var2;
int var4 = (int)(var3 * var2);
System.out.println(var4);
A.
int형 데이터끼리의 연산은 항상 int형 데이터(정수 타입)로 나온다.
따라서, double var3 은 2.5가 아닌 2가 되고
int var4 는 4 가 된다.
만약, va1 과 var2 中 최소 1 개라도 double/float(실수 타입)로 강제 변환 했다면,
모두 double 타입으로 변환되어 연산 결과는 2.5가 나왔을 것이다.
이때 최종 출력 결과는 5가 될 수 있다.
음수와 나누기(%)
class Main {
public static void main(String[] args) {
System.out.println(-10 % 8); // -2
System.out.println(10 % 8); // 2
System.out.println(-10 % -8); // -2
}
}
(* 타입 변환 中 자동 타입 변환 中 연산에서 문자열 자동 타입 변환 참고)
“JDK” + 3 + 3.0; —> “JDK3” + 3.0; —> “JDK33.0”
3 + 3.0 + “JDK” —> 6.0 + “JDK” —> “6.0JDK”
참고: 타입 - 자동 타입 변환 - 5. 연산에서 문자열 자동 타입 변환
3 순위
int x = 64; // -64;
int n = 2;
System.out.println("x >> n = " + (x >> n)); // 나눗셈, (x / 2^n)
System.out.println("x << n = " + (x << n)); // 곱셈, (x * 2^n)
System.out.println("x >>> n = " + (x >>> n));
System.out.println("x >> 34 = " + (x >> 34)); // x / 2^(n % 32)
System.out.println("x << 34 = " + (x << 34));
System.out.println("x >>> 34 = " + (x >>> 34));
>>
: bit값을 오른쪽으로 이동 (빈 자리는 부호값으로 대입) 한다.<<
: bit값을 왼쪽으로 이동 (빈 자리는 0으로 대입) 한다.>>>
: bit값을 오른쪽으로 이동 (빈 자리는 0으로 대입) 한다.4 순위
// 0.1f의 근사값은 0.1보다 큰 값이 나오기 때문
0.1 == 0.1f // false
/* 해결법
1. 모두 float 타입으로 변환
2. 정수 타입으로 변환 */
대소 연산자(<, <=, >, >=) : boolean타입(논리)을 제외하고 모두 사용 가능
동등 연산자(==, !=) : 모두 사용 가능 (!= 는 두 피연사자의 값이 다른지 검사)
조건문(if), 반복문(for, while)에 주로 사용
char 타입 : 유니코드 값으로 비교 연산
피연산자 타입을 동일하게 만든다
~이상 ~이하에서 조건식을 작성할 경우
-100 <= num <= 100 (X)
-100 <= num && num <= 100 (O) 처럼 따로 작성해줘야한다.
class Operator6_1 {
public static void main(String[] args) {
int n1 = 10, n2 = 6;
char c1 = 'A', c2 = 'B';
System.out.print("n1 >= n2 = " ); // true
System.out.println(n1 >= n2);
System.out.print("n1 <= n2 = " ); // false
System.out.println(n1 <= n2);
System.out.print("n1 == n2 = " ); // false
System.out.println(n1 == n2);
System.out.print("n1 != n2 = " ); // true
System.out.println(n1 != n2);
// 산술변환 규칙에 의해서 char 타입이 int 타입으로 변환되어 연산됨
System.out.print("c1 < c2 = "); // true
System.out.println(c1 < c2); // 65 < 66
System.out.print("c1 > c2 = "); // false
System.out.println(c1 > c2); // 65 > 66
}
}
! 는 1 순위
&, |, ^ 는 5 순위
&&, || 는 6 순위
boolean타입(논리)만 사용 가능
&&, || 는 &, | 보다 효율적으로 동작함
→ 앞의 연사자가 false 라면, 뒤의 연산자를 평가하지 않고 바로 false라는 산출 결과를 내기 때문
예시
System.out.println(true || true) // true
System.out.println(true || true || false) // true
System.out.println(true && false ) // false
System.out.println(true && true) // true
System.out.println(true) // false
8 순위
단순 대입 연산 : 오른 쪽 피연산자의 값을 변수에 저장
복합 대입 연산 : 정해진 연산 수행 후, 결과를 변수에 저장
=
: 왼쪽의 피연산자에 오른쪽의 피연산자를 대입
+=
: 왼쪽의 피연산자에 오른쪽의 피연산자를 더한 후, 그 결괏값을 왼쪽의 피연산자에 대입
-=
: 왼쪽의 피연산자에서 오른쪽의 피연산자를 뺀 후, 그 결괏값을 왼쪽의 피연산자에 대입
*=
: 왼쪽의 피연산자에 오른쪽의 피연산자를 곱한 후, 그 결괏값을 왼쪽의 피연산자에 대입
/=
: 왼쪽의 피연산자를 오른쪽의 피연산자로 나눈 후, 그 결괏값을 왼쪽의 피연산자에 대입
%=
: 왼쪽의 피연산자를 오른쪽의 피연산자로 나눈 후, 그 나머지를 왼쪽의 피연산자에 대입
&=
: 왼쪽의 피연산자를 오른쪽의 피연산자와 비트 AND 연산한 후, 그 결괏값을 왼쪽의 피연산자에 대입
!=
: 왼쪽의 피연산자를 오른쪽의 피연산자와 비트 OR 연산한 후, 그 결괏값을 왼쪽의 피연산자에 대입
^=
: 왼쪽의 피연산자를 오른쪽의 피연산자와 비트 XOR 연산한 후, 그 결괏값을 왼쪽의 피연산자에 대입
<<=
: 왼쪽의 피연산자를 오른쪽의 피연산자만큼 왼쪽 시프트한 후, 그 결괏값을 왼쪽의 피연산자에 대입
>>=
: 왼쪽의 피연산자를 오른쪽의 피연산자만큼 부호를 유지하며 오른쪽 시프트한 후, 그 결괏값을 왼쪽의 피연산자에 대입
>>>=
: 왼쪽의 피연산자를 오른쪽의 피연산자만큼 부호에 상관없이 오른쪽 시프트한 후, 그 결괏값을 왼쪽의 피연산자에 대입
class Operator8_2 {
public static void main(String[] args) {
int num1 = 7, num2 = 7, num3 = 7;
num1 = num1 - 3;
num2 -= 3;
num3 =- 3;
// = 위치를 주의
System.out.println("=- 연산자에 의한 결과 : "+ num3); // -3
}
}
i *= 10 + j
// 올바른 풀이
i = i * (10 + j)
// 잘못된 풀이 : i * 10이 먼저 연산이 돼버린다.
i = i * 10 + j
&
: 대응되는 비트가 모두 1이면 1을 반환함. (비트 AND 연산)
|
: 대응되는 비트 중에서 하나라도 1이면 1을 반환함. (비트 OR 연산)
^
: 대응되는 비트가 서로 다르면 1을 반환함. (비트 XOR 연산)
~
: 비트를 1이면 0으로, 0이면 1로 반전 시킴. (비트 NOT 연산, 1의 보수)
<<
: 명시된 수만큼 비트들을 전부 왼쪽으로 이동시킴. (left shift 연산)
>>
: 부호를 유지하면서 지정한 수만큼 비트를 전부 오른쪽으로 이동시킴. (right shift 연산)
>>>
: 지정한 수만큼 비트를 전부 오른쪽으로 이동 시키며, 새로운 비트는 전부 0이 됨
class Operator7_2 {
public static void main(String[] args) {
int num1 = 8, num2 = -8;
System.out.println("8의 2진수 = " + Integer.toBinaryString(num1)); // 0 생략 가능!
System.out.println("-8의 2진수 = " + Integer.toBinaryString(num2));
System.out.println("-9의 2진수 = " + Integer.toBinaryString(-9)); // 32bit, int = 4byte
// 00000000000000000000000000001000 , 8
// 11111111111111111111111111111000 , -8
System.out.println("& 연산자에 의한 결과 = " + (num1 & num2)); // 00000000000000000000000000001000, 8
System.out.println("| 연산자에 의한 결과 = " + (num1 | num2)); // 11111111111111111111111111111000, -8
System.out.println("^ 연산자에 의한 결과 = " + (num1 ^ num2)); // 11111111111111111111111111110000, -16
System.out.println("~ 연산자에 의한 결과 = " + ~num1); // 11111111111111111111111111110111, -9
System.out.println("<< 연산자에 의한 결과 = " + (num1 << 2)); // 32
System.out.println(">> 연산자에 의한 결과 = " + (num2 >> 2)); // -2
System.out.println(">>> 연산자에 의한 결과 = " + (num2 >>> 2)); // 1073741822
}
}
?, : 는 7 순위
조건식 ? 값 또는 연산식 : 값 또는 연산식
(피연산자1) (피연산자2) (피연산자3)
// 예시
// score는 85점 이므로, false -> ((score > 80) ? 'B' : 'C') -> score는 85점 이므로, true -> B
int score = 85;
char grade = (score > 90) ? 'A' : ((score > 80) ? 'B' : 'C');
System.out.println(score + "점은" + grade + "등급입니다.");
/* 실행결과
85점은 B등급입니다.
*/
class Operator1_1 {
public static void main(String[] args) {
int x = 10;
int y = 20;
// + 연산자는 피연산자가 2개인 이항 연산자 임으로 단항 연산자인 -x 의 -가 먼저 실행된다.
System.out.print("-x + 3 = ");
System.out.println(-x + 3); // -10 + 3 = -7
System.out.print("x + 3 * y = ");
System.out.println(x + 3 * y); // 10 + (3 * 20) = 70
System.out.print("x + 3 > y - 2 = ");
System.out.println(x + 3 > y - 2); // false
System.out.print("x + 3 < y - 2 = ");
System.out.println(x + 3 < y - 2); // true
System.out.print("x > 3 && y < 2 = ");
System.out.println(x > 3 && y < 2); // false
int result = x + y * 3;
System.out.println("result = " + result); // 10 + (20 * 3), result = 70
}
}