- 자바 언어 기초(com.eomcs.lang)
- ex05 : 연산자 사용법
- 실습 프로젝트 : mini-pms(프로젝트 관리 시스템)
- 3 단계: 변수와 키보드 입력 다루기 (해설)
- 학습 목표 달성 확인 목록
- [] 자바에서 제공하는 연산자를 사용할 수 있는가?
연산자 우선 순위
괄호: ()
후위 연산자: a++, a–
전위 연산자: ++a, –a, 단항 연산자(+, -)
*, /, %
+, -
비트이동 연산자: «, », »>
관계 연산자: <, >, <=, >=, instanceof
등위 연산자: ==, !=
&
|
논리 연산자 AND: &&
논리 연산자 OR: ||
삼항 연산자: (조건) ? 값 : 값
할당 연산자: =, +=, -=, *=, /=, %=, &=, ^=, |=, «=, »=, »>=
- [] 정수 연산에서 최소 연산 단위가 int임을 이해하는가?
byte/short와는 성능차이가 별로없기 때문이다.
(연산하면 암시적 형변환으로 int형으로 변환된다.)
- [] 연산 우선 순위를 이해하는가?
산술 연산자에서는 *,/,%이 +,-보다 먼저 계산하며
사용자가 선택한 식을 먼저 계산하고 싶으면 ()괄호를 이용하여 적용해준다.
- [] 연산은 같은 타입이어야만 수행할 수 있다는 것을 아는가?
int+int = int
float+float = float
두 식을 보듯이 연산 결과는 피연산자의 타입과 같다
그래서 두 값을 계산했을때 결과 메모리를 초과할 경우
값이 짤릴 수 있다!
그래서 계산결과가 크게 나올거 같으면 처음부터 피연산자의 값을 더 큰 메모리에 담아서 연산해야된다.
- [] 연산의 결과는 피연산자의 타입과 같다는 것을 아는가?
int+int = int
float+float = float
double+double = double
- [] 암시적 형변환을 설명할 수 있는가?
정수의 경우 기본단위는 int이다
따라서 int보다 작은 크기의 메모리값을 다룰때는 내부적으로 int로 자동 형변환이되어 연산을 수행한다
이렇게 내부적으로 자동 형변환하는 것을 암시적 형변환이라고 한다.
- [] 명시적 형변환을 사용할 수 있는가?
큰 메모리의 값을 작은 메모리에 넣으려고 형변환을 사용하기도 하는데
다만 형변환하더라도(즉 작은 메모리에 넣더라도) 값이 잘리지 않을 때만 하는것을 추천한다.
한마디로 형변환하더라도 값이 소실되지 않을 때만 명시적 형변환을 하는것을 추천한다.
- [] 부동소수점의 값을 비교할 때 극소수의 값을 고려해야 함을 이해하는가?
컴퓨터가 부동소수점 값을 연산할 때는 IEEE 754 명세에 따라 작업을 수행한다
이 과정에서 값의 왜곡이 발생할 수 있다.이문제는 모든 컴퓨터에서 발생하는 문제이다.
따라서 부동소수점은 비교연산자를 사용하여 비교할 때
극소수값을 처리해주는 코드가 따로 필요하다
double EPSILON = 0.00001;
System.out.println(Math.abs((d1 + d2) - (x + y)) < EPSILON);
- EPSILON 값을 선언한다.
- 각각 연산에서 계산한 값의 오차를 구한다.
- Math.abs() 메소드를 사용하여 오차에 절대값을 구한다.
- 이 오차의 절대값이 EPSILON보다 작다면 두 결과값을 같은 값으로 취급한다.
- [] 관계 연산자(>, >=, <, <=, ==, !=)를 다룰 수 있는가?
관계 연산자(relational operators: <, <=, >, >=)
등위 연산자(equality operators: ==, !=)
비교결과는 boolean값으로 나온다.
- [] 부동소수점의 값을 비교할 때 주의할 사항이 무엇인가?
부동소수점 값을 연산할 때는 IEEE 754 명세에 따라 작업을 수행하는데
여기서 값의 왜곡이 발생한다.그래서 위의 코드처럼 비교군을 만들어서 비교해준다.
| **- [] 논리 연산자(&&, | ,!,^,&, | )를 다룰 수 있는가?** |
// AND 연산자
// - 두 개의 논리 값이 모두 true일 때 결과가 true가 된다.
System.out.println(true && true);
System.out.println(true && false);
System.out.println(false && true);
System.out.println(false && false);
//결과
true
false
false
false
// OR 연산자
// - 두 개의 논리 값 중 한 개라도 true이면 결과는 true가 된다.
System.out.println(true || true);
System.out.println(true || false);
System.out.println(false || true);
System.out.println(false || false);
//결과
true
true
true
false
// NOT 연산자
// - true는 false로 false는 true로 바꾼다.
System.out.println(!true);
System.out.println(!false);
//결과
false
true
// exclusive-OR(XOR)연산자
// - 배타적 비교 연산자라 부른다.
// - 두 개의 값이 다를 때 true이다.
System.out.println(true ^ true);
System.out.println(false ^ false);
System.out.println(true ^ false);
//결과
false
false
true
| **- [] &&와 &, | 와 | 논리 연산자의 차이점을 아는가?** |
| &&, | 는 앞의 피연산자의 값으로 결과를 알 수 있다면 뒤의 명령은 실행하지 않는다 |
| &, | 는 앞의 피연산자로 결과를 알더라도 뒤의 명령까지 모두 실행한다. |
| **- [] 비트 연산자(&, | ,^,~)를 다룰 수 있는가?** |
AND연산자
자릿수가 서로 1로 일치할때만 1이 되며
그외의 경우엔 모두 0이 된다
(여기서 1이란 참,0이란 거짓으로 봐도 무방하다)
0 0 1 0 1
AND 0 1 0 1 0
0 0 0 0 0
0 0 1 0 1
AND 0 1 1 1 1
0 0 1 0 1
OR연산자
이 녀석은 단 하나라도 자리에 1이 있으면 연산되는 해당 자리수의 값을 1로 만든다
or 연산자의 기호는 파이프 기로하 부르는데
엔터 위에 \를 쉬프트와 같이 누르면 된다
00101
or 01010
01111
00100
or 01110
01110
00101
or 01110
01111
XOR연산자
^ 같은 갈매기 표시는 6과 시프트를 같이 누른다
같은 자리에 배치된 값이 서로 다른 경우에만 1이 된다
00101
xor 01010
01111
00100
xor 01 1 10
01010
not연산자 ~
모든것을 반전한다
단순한 방법:not의 대상이 되는 값 +1을 하고 부호를 반전한다
- [] 비트 연산자로 % 연산을 수행하는 방법을 아는가?
어떤 값에 대해 4로 나눈 나머지 값을 구하고 싶다면,
& 연산자를 이용하여 그 값의 하위 2비트 값만 추출하면 된다.
주의!
=> & 연산자를 사용해서 나머지 값을 구하려면
나누는 값이 2의 제곱수여야 한다.
=> 즉 2의 제곱수로 나눈 나머지 값을 구하는 경우에는
% 대신 비트 연산자 &를 사용하면 계산 속도가 빠르다.
- [] 비트 연산자를 활용하여 특정 값만 추출하는 방법을 아는가?
int data = 0b1111_1001_0111_1111;
System.out.println(Integer.toBinaryString(data & 0b0000_1111_1100_0000));
1111_1001_0111_1111
& 0000_1111_1100_0000
-----------------------
0000_1001_0100_0000
- [] 비트 연산자를 활용하여 여러 개의 true/false 값을 한 변수에서 다룰 수 있는가?
// 특정 비트의 값을 설정할 때
// 0x01, 0x02, 0x04, 0x08 처럼 직접 숫자를 사용하면
// 코드를 읽고 이해하기가 쉽지 않다.
// 해결책?
// - 각각의 값을 의미있는 이름을 가진 변수에 저장한 후 사용하라.
// - 또한 조회용으로 사용할 변수이므로 상수로 선언하라.
//
//
final int CSS = 0x01; // 0000 0001
final int HTML = 0x02; // 0000 0010
final int PHP = 0x04; // 0000 0100
final int PYTHON = 0x08; // 0000 1000
final int JAVASCRIPT = 0x10; // 0001 0000
final int JAVA = 0x20; // 0010 0000
final int CPP = 0x40; // 0100 0000
final int C = 0x80; // 1000 0000
// Java와 C, C++, JavaScript를 할 줄 아는 개발자의 정보를 설정하라!
int lang = C | JAVA | PYTHON | HTML;
// 1000 0000 (C)
// | 0010 0000 (JAVA)
// | 0000 1000 (PYTHON)
// | 0000 0010 (HTML)
// -------------------
// 1010 1010
//
System.out.println(Integer.toBinaryString(lang));
- [] 비트 이동 연산자(«, », »>)를 다룰 수 있는가?
| 연산식 | 설명 |
| x « y | 정수 x의 각 비트를 y만큼 왼쪽으로 이동시킨다. (빈자리는 0으로 채워진다.) |
| x » y | 정수 x의 각 비트를 y만큼 오른쪽으로 이동시킨다. (빈자리는 정수 a의 최상위 부호비트와 같은 값으로 채워진다.) |
| x »> y | 정수 x의 각 비트를 y만큼 오른쪽으로 이동시킨다. (빈자리는 0으로 채워진다.) |
2 « 3

16 » 3

-16 » 3

-16 »> 3

- [] 비트 이동 연산자를 사용하여 2의 배수를 곱하고 나누는 방법을 아는가?
« 1비트 이동은 곱하기 2를 한 것과 같은 효과이다.
int i = 1;
// [00000000000000000000000000000001] = 1
System.out.println(i << 1);
// 0[0000000000000000000000000000001 ]
// [00000000000000000000000000000010] = 2
System.out.println(i << 2);
// 00[000000000000000000000000000001 ]
// [00000000000000000000000000000100] = 4
System.out.println(i << 3);
// 000[00000000000000000000000000001 ]
// [00000000000000000000000000001000] = 8
System.out.println(i << 4);
// 0000[0000000000000000000000000001 ]
// [00000000000000000000000000010000] = 16
i = 11; // [00000000000000000000000000001011]
System.out.println(i << 1); // 0[00000000000000000000000000010110] => 22
System.out.println(i << 2); // 00[00000000000000000000000000101100] => 44
System.out.println(i << 3); // 000[00000000000000000000000001011000] => 88
»1비트 이동은 나누기 2 한 것과 같은 효과이다.
int i = 105; // [00000000000000000000000001101001]
System.out.println(i); // => 105
System.out.println(i >> 1);
// [ 0000000000000000000000000110100]1
// [00000000000000000000000000110100] => 52
System.out.println(i >> 2);
// [ 000000000000000000000000011010]01
// [00000000000000000000000000011010] => 26
System.out.println(i >> 3);
// [ 00000000000000000000000001101]001
// [00000000000000000000000000001101] => 13
System.out.println(i >> 4);
// [ 0000000000000000000000000110]1001
// [00000000000000000000000000000110] => 6
- [] 조건 연산자(?:)를 다룰 수 있는가?
// 조건연산자
// => 조건 ? 표현식1 : 표현식2
// => 조건이 참이면 표현식1을 실행하고,
// 조건이 거짓이면 표현식2를 실행한다.
int age = 20;
String message = (age > 18) ? "성년" : "미성년";
System.out.printf("나이 %d는(은) %s이다.\n", age, message);
//결과
나이 20는(은) 성년이다.
- [] ++/– 후위 연산자 및 전위 연산자를 다룰 수 있는가?
int i = 1;
System.out.println(i);//1
i++;
System.out.println(i);//2
++i;
System.out.println(i);//3
쉽게 설명하면 변수가 부호를 앞으로 지나가는가 뒤로지나가는가에 따라 값이 달라진다.

- [] 복합 할당 연산자(+=, -=, *=, /=, %= 등)를 다룰 수 있는가?
int i = 1;
i+=1;
int j = 2;
j*=2;
i는 1씩 더해서 축적된다.1->2->3…
j는 2씩 곱해서 축적된다.2->4->8…