자바의 정석 | Ch 03 - 연산자(Operator)
by 무작정 개발1. 연산자(operator)
1.1 연산자와 피연산자
연산자가 연산을 수행하려면 반드시 연산의 대상이 있어야 하는데, 이것을 '피연산자(operand)'라고 한다.
연산자(operator) : 연산을 수행하는 기호(+, -, *, / 등)
피연산자(operand) : 연산자의 작업 대상(변수, 상수, 리터럴, 수식)
1.2 식과 대입 연산자
y = 4 * 5 + 3
y = 23; // 식의 평과 결과가 변수 y에 저장된다.
System.out.println(y); // 변수 y의 값을 화면에 출력
1.3 연산자의 종류
연산자는 하단 표를 보면 알 수 있는 것처럼, 크게 산술, 비교, 논리, 대입 4가지로 나눌 수 있다.
종류 | 연산자 | 설명 |
산술 연산자 | + - * / % << >> | 사칙 연산(+,-,*,/)과 나머지 연산(%) |
비교 연산자 | > < >= <= == != | 크고 작음과 같고 다름을 비교 |
논리 연산자 | && || ! & | ^ ~ | '그리고(AND)'와 '또는(OR)'으로 조건을 연결 |
대입 연산자 | = | 우변의 값을 좌변에 저장 |
기타 | (type) ?: instanceof | 형변환 연산자, 삼항 연산자, instanceof연산자 |
2. 단항 연산자
2.1 증감 연산자 ++ , --
증감 연산자는 피연산자에 저장된 값을 1 증가 또는 감소시킨다. 증감 연산자의 피연산자로 정수와 실수가 모두 가능하지만, 상수는 값을
변경할 수 없으므로 가능하지 않다. 그리고 대부분의 연산자는 피연산자의 값을 읽어서 연산에 사용할 뿐, 피연산자의 타입이나 값을
변경시키지 않는다. 오직 대입 연산자와 증감 연산자만 피연산자의 값을 변경한다.
<참고> 증감 연산자는 일반 산술 변환에 의한 자동 형 변환이 발생하지 않으며, 연산 결과의 타입은 피연산자의 타입과 같다.
증가 연산자(++) : 피연산자의 값을 1 증가시킨다.
감소 연산자(--) : 피연산자의 값을 1 감소시킨다.
증감, 감소 연산자는 피연산자 양쪽 모두에 위치할 수 있다. 왼쪽에 위치하면 '전위형(prefix), 오른쪽에 위치하면 '후위형(postifx)이라고
한다. 이 부분은 헷갈릴 수 있어 정확하게 알고 있어야 한다. 필자도 학교 수업을 들을 때 헷갈려했고, 정보처리기사 시험에 전위, 후위 계산식 등 문제가 나오기 때문에 확실히 알고 있어야 한다.
전위형과 후위형 모두 피연산자의 값을 1 증가 또는 감소시키지만, 증감 연산자가 수식이나 메서드 호출에 포함된 경우 전위형일 때와
후위형일 때의 결과가 다르다. 하지만 메서드 호출에 포함되지 않고 독립적인 하나의 문장으로 쓰인 경우에는 차이가 없다.
타입 | 설명 | 예시 |
전위형 | 값이 참조되기 전에 증가시킨다. | j =. ++i; |
후위형 | 값이 참조된 후에 증가시킨다. | j = i++; |
//예제3-1/ch3/OperatorEx1.java
package Chapter03;
public class OperatorEx1 {
public static void main(String[] args) {
int i=5;
i++; //i=i+1; 과 같은 의미다. ++i;로 바꿔 써도 결과는 같다.
System.out.println(i);
i=5;
++i; // 결과를 비교하기 위해 i값을 다시 5로 변경.
System.out.println(i);
}
}
위의 결과는 보면 한 번은 전위형(++i), 두 번째는 후위형(i++)을 사용했는데 결과는 i의 초기값 5에서 1 증가된 6이 출력됨을 알 수 있다.
위에서 말한 대로 어떤 수식에 포함된 것이 아니라 단독적으로 사용된 것이기에 차이가 없다.
그러나 다른 수식에 포함되거나 메서드의 매개변수로 사용된 경우, 결과는 다르다. 하단 예제를 풀어보자!
//예제3-2/ch3/OperatorEx2.java
package Chapter03;
public class OperatorEx2 {
public static void main(String[] args) {
int i = 5, j = 0;
j = i++; //후위 : 값이 참조된 후에 증가시킨다. 쉽게 말하자면 i의 값 5를 j에 넣고 i를 1증가시킨다. 그러면 j는 5, i는 6이다.
System.out.println("j = i++; 실행 후, i =" + i +", j = " + j);
i = 5; // 결과를 비교하기 위해, i와 j의 값을 다시 5와 0으로 변경
j = 0;
j = ++i; // 전위 : 값이 참조되기 전에 증가시킨다. 쉽게 말하자면 i의 값 5를 j에 넣기전에 1증가시키고 넣는다. 그러면 j는 6, i는 6이다.
System.out.println("j = ++i; 실행 후, i =" + i +", j = " + j);
}
} //실행결과 :
//j = i++; 실행 후, i =6, j = 5
//j = ++i; 실행 후, i =6, j = 6
실행 결과를 보면 전위형(++i)은 변수(피연산자)의 값을 먼저 증가시킨 후에 변수의 값을 읽어오는 반면, 후위형(i++)은 변수의 값을 먼저 읽어온 후에 값을 증가시킨다. 위의 예제가 이해된다면 하단 메서드 호출에 증감 연산자 예제를 풀어보자!!
//예제3-3/ch3/OperatorEx3.java
package Chapter03;
public class OperatorEx3 {
public static void main(String[] args) {
int i = 5, j = 5;
System.out.println(i++); //결과 : 5
// i++은 후위형이라 값이 참조된 후에 증가시킨다. 그래서 println()에게 i의 값 5를 넘겨주고 나서 i의 값이 증가하기에 결과는 5출력
System.out.println(++j); //결과 : 6
// ++j은 전위형이라 값이 참조되기 전에 증가시킨다. 그래서 println()에게 j의 값을 넘겨주기전에 1 중가시켜 6을 넘겨줘서 결과는 6출력
System.out.println("i = " + i + ", j = " + j); // 결과 : i = 6, j = 6;
//위에서 결과는 5와 6이 출력됬지만 i와 j는 모두 6이 들어있다. 따라서 둘다 6으로 출력된다.
}
}
위의 증감 연산자 예제 3개를 풀어보면 대략 이해가 될 것이다. 필자는 일단 따라 써보고 결과를 보고 왜 이렇게 결과가 나오는지 그림을
그려가며 진행사항을 체크하면서 이해를 했다. 증감 연산자를 사용하면 코드가 간결해지지만, 지나치면 복잡해져서 하나의 식에 증감 연산자의 사용을 최소화하고, 식에 2번 이상 포함된 변수에 증감 연산자를 사용하는 것은 피해야 한다.
감소 연산자(--)는 값이 1 감소시킨다는 것만 빼면 증가 연산자(++)와 동일하다.
2.2 부호 연산자
부호 연산자 '-'는 피연산자의 부호를 반대로 변경한 결과를 반환한다. 피연산자가 음수면 양수, 양수면 음수가 연산의 결과가 된다.
부호 연산자'+'는 하는 일이 없고, 쓰이는 경우도 거의 없다. 부호 연산자는 boolean형과 char형을 제외한 기본형에만 사용 가능하다.
<참고> 부호 연산자는 덧셈, 뺄셈 연산자와 같은 기호를 쓰지만 다른 연산자이다. 기호는 같아도 피연산자의 개수가 달라서 구별 가능.
//예제3-4/ch3/OperatorEx4.java
package Chapter03;
public class OperatorEx4 {
public static void main(String[] args) {
int i = -10;
i = +i;
System.out.println(i); //결과 : -10
i = -10;
i = -i;
System.out.println(i); // 결과 : 10
}
}
3. 산술 연산자
산술 연산자에는 사칙 연산자(+-*/)와 나머지 연산자(%)가 있다.
3.1 사칙 연산자 + - * /
//예제3-5/ch3/OperatorEx5.java
package Chapter03;
public class OperatorEx5 {
public static void main(String[] args) {
int a = 10;
int b= 4;
System.out.printf("%d + %d = %d%n", a, b, a+b);// 10 + 4 = 14
System.out.printf("%d - %d = %d%n", a, b, a-b);// 10 - 4 = 6
System.out.printf("%d * %d = %d%n", a, b, a*b);//10 * 4 = 40
System.out.printf("%d / %d = %d%n", a, b, a/b);//10 / 4 = 2
System.out.printf("%d / %f = %f%n", a, (float)b, a / (float)b);//10 / 4.000000 = 2.500000
}
}
System.out.printf("%d / %d = %d%n", a, b, a/b);//10 / 4 = 2
상단 부분을 보면 10 나누기 4를 한 결과가 2.5가 아닌 2라는 것을 알 수 있다. 나누기 연산자의 두 피연산자가 모두 int타입인 경우,
연산 결과 역시 int타입이다. 그래서 설제 연산 결과는 2.5일지라도 int타입의 값인 2를 결과로 얻는다. int타입은 소수점을 저장하지
못하므로 정수만 남고 소수점 이하는 버려지기 때문이다. 반올림은 하지 않는다.@@중요@@
System.out.printf("%d / %f = %f%n", a, (float)b, a / (float)b);//10 / 4.000000 = 2.500000
다음으로 상단 부분을 보자. 10 나누기 4를 한 결과가 2.500000가 나왔다. 위의 문제를 해결하고 올바른 연산 결과를 얻기 위해서는
두 피연산자 중 어느 한쪽을 실수형으로 형 변환해야 한다. 그래야만 다른 한쪽도 같이 실수형으로 자동 형 변환되어 결국 실수형의 값을
결과로 얻는다. 위의 과정을 보면 b는 int타입이라 float을 써서 float타입으로 일치시킨다. 그래서 (float) b로 썼다.
책에서 크게 중요하지 않다고 한 부분은 생략하였다. 하지만 자바의 정석 3판이 있는 분들은 생략한 부분도 읽어보고 예제를 진행해보시는 걸 추천한다. 생략한 부분은 예제 3-6(p98)부터 예제 3-18(p107)까지 이다. 자세한 건 책을 참고하자.
3.2 나머지 연산자 %
나머지 연산자는 왼쪽의 피연산자를 오른쪽 피연산자로 나누고 난 나머지 값을 결과로 반환하는 연산자이다. 그리고 나눗셈처럼
나누는 수(오른쪽 피연산자)로 0을 사용할 수 없다. 나머지 연산자는 주로 짝수, 홀수 or 배수 검사 등에 주로 사용한다.
하단 예제는 나눗셈 연산자와 나머지 연산자를 이용해서 몫과 나머지를 구하는 예제이다. 간단한 예제이니 한번 풀어보자!!
//예제3-19/ch3/OperatorEx19.java
package Chapter03;
public class OperatorEx19 {
public static void main(String[] args) {
int x = 10;
int y = 8;
System.out.printf("%d을 %d로 나누면, %n", x, y);
System.out.printf("몫은 %d이고, 나머지는 %d입니다.%n", x / y, x % y);
}
}//실행 결과 :
//10을 8로 나누면,
//몫은 1이고, 나머지는 2입니다.
상단 예제를 풀어봤으면 하단 예제를 풀어보자!!
//예제3-20/ch3/OperatorEx20.java
package Chapter03;
public class OperatorEx20 {
public static void main(String[] args) {
System.out.println(-10 % 8); // 결과 : -2
System.out.println(10 % -8); // 결과 : 2
System.out.println(-10 % 8); // 결과 : -2
}
}
나머지 연산(%)은 나누는 수로 음수도 허용된다. 그러나 부호는 무시되므로 결과는 음수의 절댓값으로 나눈 나머지와 결과가 같다.
ex)
System.out.println(10 % 8); // 10을 8로 나눈 나머지 2가 출력된다.
System.out.println(10 % -8); // 위와 같은 결과를 얻는다.
그냥 피연산자의 부호를 모두 무시하고, 나머지 연산을 한 결과에 왼쪽 피연산자(나눠지는 수)의 부호를 붙이면 된다.
4. 비교 연산자
비교 연산자는 두 피연산자를 비교하는 데 사용되는 연산자이다. 주로 조건문과 반복문의 조건식에 사용되며, 연산 결과는 오직 true와
false 둘 중의 하나이다. 비교 연산자 역시 이항 연산자이므로 비교하는 피연산자의 타입이 서로 다를 경우에는 자료형의 범위가
큰 쪽으로 자동 형 변환하여 피연산자의 타입을 일치시킨 후에 비교한다는 점에 주의하자!!!
4.1 대소 비교 연산자 < > <= >=
대소 비교 연산자는 두 피연산자의 값의 크기를 비교하는 연산자이다. 참이면 true를, 거짓이면 false를 결과로 반환한다. 기본형 중에서는
boolean형을 제외한 나머지 자료형에 다 사용할 수 있지만 참조형에는 사용할 수 없다.
<대소 비교 연산자의 종류와 연산 결과>
비교연산자 | 연산결과 |
> | 죄변 값이 크면, true 아니면 false |
< | 좌변 값이 작으면, true 아니면 false |
>= | 좌변 값이 크거나 같으면, true 아니면 false |
<= | 좌변 값이 작거나 같으면, true 아니면 false |
4.2 등가 비교 연산자 ==!=
등가 비교 연산자는 두 피연산자의 값이 같은지 또는 다른지를 비교하는 연산자이다. 대소 비교 연산자(< , >, <=, >=)와는 달리, 기본형은
물론 참조형, 즉 모든 자료형에 사용할 수 있다. 기본형의 경우 변수에 저장되어 있는 값이 같은지를 알 수 있고, 참조형의 경우 객체의
주소 값을 저장하기 때문에 2개의 피연산자(참조 변수)가 같은 객체를 가리키고 있는지 알 수 있다.
기본형과 참조형은 서로 형 변환이 가능하지 않기 때문에 등가 비교 연산자(==,!=)로 기본형과 참조형을 비교한다.
<등가 비교 연산자의 종류와 연산 결과>
비교연산자 | 연산결과 |
== | 두 값이 같으면, true 다르면. false |
!= | 두 값이 다르면, true 같으면 false |
//예제3-21/ch3/OperatorEx21.java
package Chapter03;
public class OperatorEx21 {
public static void main(String[] args) {
System.out.printf("10 == 10.0f \t %b%n", 10 == 10.0f);
System.out.printf("'0' == 0 \t %b%n", '0' == 0);
System.out.printf("'A' == 65 \t %b%n", 'A' == 65);
System.out.printf("'A' > 'B' \t %b%n", 'A' > 'B');
System.out.printf("'A'+1 != 'B' \t %b%n", 'A' + 1 != 'B');
}
}
//결과 :
// 10 == 10.0f true
// '0' == 0 false
// 'A' == 65 true
// 'A' > 'B' false
// 'A'+1 != 'B' false
위의 예제에서 한 부분을 체크해보자.
System.out.printf("10 == 10.0f \t %b%n", 10 == 10.0f);
비교 연산자도 이항 연산자이므로 연산을 수행하기 전에 형 변환을 통해 두 피연산자의 타입을 같게 맞춘 다음 피연산자를
비교한다. 10 == 10.0f에서 10은 int타입이고 10.0f는 float타입이므로, 10을 float로 변환한 다음에 비교한다. 두 값이 10.0f로 같으므로
결과로 true를 얻는다.
10 == 10.0f
-->10.0f == 10.0f
--> true
위의 부분을 이해했으면 예제의 하단 코드 나머지를 보자!!
문자 'A'의 유니코드는 10진수로 65이고, 'B'는 66, '0'은 48이므로 나머지 식들은 다음과 같은 과정으로 연산된다.
'0' == 0 -> 48 == 0 -> false
'A' == 65. -> 65 == 65 -> true
'A' > 'B'. ->. 65 > 66. -> false
'A' +1!= 'B' -> 65+1!= 66 -> 66!= 66 -> false
5. 논리 연산자
5.1 논리 연산자 - &&, || ,!
논리 연산자 '&&'는 그리고(AND)를 뜻하며, 두 피연산자가 모두 true일 때만 true를 결과로 얻는다. '||'는 '또는(OR)을 뜻하고,
두 피연산자 중 어느 한 쪽만 true이어도 true를 결과로 얻는다. 그리고 논리 연산자는 피연산자로 boolean형 또는 boolean형 값을
결과로 하는 조건식만을 허용한다.
|| (OR결합) : 피연산자 중 어느 한 쪽만 true이면 true를 결과로 얻는다.
&& (AND결합) : 피연산자 양쪽 모두. true이어야 true를 결과로 얻는다.
위의 내용을 이해했으면 하단 예제를 풀어봅시다!
//예제3-21/ch3/OperatorEx21.java
package Chapter03;
public class OperatorEx24 {
public static void main(String[] args) {
int x = 0;
char ch = ' ';
x = 15;
System.out.printf("x = %2d, 10 < x && x < 20 = %b%n", x, 10 < x && x < 20);
x = 6;
System.out.printf("x = %2d, x%%2 == 0 || x%%3 == 0 && x%%6! = 0 = %b%n", x, x%2 == 0 || x%3 == 0 &&x %6 != 0);
System.out.printf("x = %2d, x%%2 == 0 || x%%3 == 0 && x%%6! = 0 = %b%n", x, (x%2 == 0 || x%3 == 0) &&x %6 != 0);
ch = '1';
System.out.printf("ch = '%c', '0' <= ch && ch <= '9' =%b%n", ch, '0' <= ch && ch <= '9');
ch = 'a';
System.out.printf("ch = '%c', 'a' <= ch && ch <= 'z' =%b%n", ch, 'a' <= ch && ch <= 'z');
ch = 'A';
System.out.printf("ch = '%c', 'A' <= ch && ch <= 'Z' =%b%n", ch, 'A' <= ch && ch <= 'Z');
ch = 'q';
System.out.printf("ch = '%c', ch =='q' || ch == 'Q' = %b%n", ch, ch == 'q' || ch == 'Q');
}
}
//실행 결과:
//x = 15, 10 < x && x < 20 = true
//x = 6, x%2 == 0 || x%3 == 0 && x%6! = 0 = true
//x = 6, x%2 == 0 || x%3 == 0 && x%6! = 0 = false
//ch = '1', '0' <= ch && ch <= '9' =true
//ch = 'a', 'a' <= ch && ch <= 'z' =true
//ch = 'A', 'A' <= ch && ch <= 'Z' =true
//ch = 'q', ch =='q' || ch == 'Q' = true
저 또한 이 예제는 이해하기 어려웠습니다. 여러 번 보시면 이해가 될 것입니다. 이 예제는 논리 연산자에 대해 배운 내용들을 확인할 수 있는
간단한 예제입니다.
5.2 비트 연산자 &, |, ^, ~, <<, >>
비트 연산자는 피연산자를 비트단위로 논리 연산한다. 피연산자를 이진수로 표현했을 때의 각 자리를 아래의 규칙에 따라 하단의 표와 같이
연산을 수행하며, 피연산자로 실수는 허용하지 않는다. 정수(문자 포함)만 허용한다.
| (OR연산자) : 피연산자 중 한 쪽의 값이 1이면, 1을 결과로 얻는다. 그 외에는 0을 얻는다.
& (AND연산자) : 피연산자 양쪽이 모두 1이어야만 1을 결과로 얻는다. 그 외에는 0을 얻는다.
^ (XOR연산자) : 피연산자의 값이 서로 다를 때만 1을 결과로 얻는다. 같을 때는 0을 얻는다.
<비트 연산자의 연산결과>
x | y | x | y | x & y | x ^ y |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 1 | 0 | 1 |
0 | 1 | 1 | 0 | 1 |
0 | 0 | 0 | 0 | 0 |
비트 연산자에 관한 자세한 자료는 하단 링크를 들어가서 확인해보세요.
'Language > Java' 카테고리의 다른 글
자바의 정석 | Ch 06 - 객체지향프로그래밍1-1 (0) | 2021.12.16 |
---|---|
자바의 정석 | Ch 05 - 배열 Array (0) | 2021.12.15 |
자바의 정석 | Ch 04 - 조건문과 반복문 (0) | 2021.12.15 |
자바의 정석 | Ch 2 - 변수(Variable) (0) | 2021.12.15 |
자바의 정석 | Ch 01 - 자바를 시작하기 전에 (2) | 2021.12.13 |
블로그의 정보
무작정 개발
무작정 개발