[개념정리] Java의 정석 Chapter 3 연산자

SW/Java

2020. 7. 27. 10:21

1. 연산자(operator)

1.1 연산자와 피연산자

     연산자(operator) 연산을 수행하는 기호(+, -, *, / 등)

     피연산자(operand) 연산자의 작업 대상(변수, 상수, 리터럴, 수식)

 

1.3 연산자의 종류

# 연산자의 기능별 분류

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

# 피연산자의 개수에 의한 분류

ex)

-3-5

- 첫 번째 -는 부호 연산자, 단항 연산자

- 두 번째 -는 뺄셈 연산자, 이항 연산자

 

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

   가장 높은 것 () 

   가장 낮은 것 = 

# 연산자 우선순위의 예시와 설명 (><로 우선순위 여부 표시) 

- 단항 연산자 > 이항 연산자

  ex) -x + 3

- 곱셈/나눗셈 > 덧셈/뺄셈

  ex) x + 3 * y

- 산술연산자(+, -) > 비교연산자(>)

  ex) x + 3 > y - 2

- 비교연산자 > 논리연산자 &&

  ex) x > 3 && x < 5 

- 대입연산자는 우선순위가 가장 낮다

  ex) result = x + y * 3;

- 덧셈연산자 > shift연산자(<<)

  ex) x << 2 + 1

- 비교연산자(==) > 비트연산자(&)

  ex) data & 0xFF == 0 (문법적에러 발생되는 예시임 - true, false로는 비트연산이 불가하기 때문!)

- AND(&, &&) > OR(|, ||)

  ex) x < -1 || x > 3 && x < 5

 

# 연산자의 결합규칙

   연산자마다 다르지만, 대부분 왼쪽 → 오른쪽 순으로 연산을 수행하고,

   단항연산자와 대입연산자만 오른쪽 왼쪽 순으로 연산을 수행한다.

 

- 연산자의 우선순위와 결합규칙 정리 표 

종류 결합규칙 연산자 우선순위
단항연산자 ++ -- + - ~ ! (type) 높음





















낮음
산술연산자 * / %
+ -
<< >>
비교연산자 < > <= >= instanceof
== !=
논리연산자 &
^
|
&&
||
삼항연산자 ?:
대입연산자 = += -= *= /= %= <<= >>= &= ^= |=

 

1.5 산술변환(usual arithmetic conversion)

     연산 수행 직전에 발생하는 피연산자의 자동 형변환

- 산술변환 규칙

① 두 피연산자의 타입을 같게 일치시킨다(보다 큰 타입으로 일치)

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

 

2. 단항연산자

2.1 증감연산자(++, --)

     피연산자에 저장된 값을 1 증가 또는 1 감소시킨다.

- 전위형과 후위형의 비교

타입 설명 예시
전위형 값이 참조되기 전에 증가시킨다. j = ++i;  → ++i;  // 증가 후 
                j = i;    참조하여 대입
후위형 값이 참조된 후에 증가시킨다. j = i++; → j = i; // 참조하여 대입 후
              ㅑ++;    증가 

 

2.2 부호연산자(+, -)

     피연산자의 부호를 반대로 변경한 결과를 반환한다.

     피연산자가 음수면 양수, 양수면 음수가 연산 결과가 된다.

 

3. 산술연산자

3.1 사칙연산자(+, -, *, /)

- 정수형은 나눈 결과에서 소수점 이하는 버려진다.

  ex) int 10 / int 4 → int 2

 

- 크기가 작은 자료형의 변수를 큰 자료형의 변수에 저장할 때는 자동형변환 되지만,

  반대로 크기가 큰 자료형의 값을 작은 자료형의 변수에 저장하려면

  명시적으로 형변환 연산자를 사용해서 변환해주어야 한다.

 

# 숫자와 영문자의 유니코드표

문자 코드 문자 코드 문자 코드
0 48 A 65 a 97
1 49 B 66 b 98
2 50 C 67 c 99
3 51 D 68 d 100
4 52 E 69 e 101
5 53 ... ... ... ...
.. .. X 88 x 120
8 56 Y 89 y 121
9 57 Z 90 z 122

 // Tip : 유니코드를 모를 땐 

           ex) char ch = 'A';

                System.out.print((int)ch); 를 작성해 확인해보기!

 

- 리터럴, 상수 간의 연산은 형변환 해주지 않아도

  실행과정동안 변하는 값이 아니기 때문에 컴파일 시 컴파일러가 계산하여 그 결과로 대체한다.

  이로 인해, 코드를 보다 효율적으로 만들어준다.

 

  반대로 코드의 가독성과 유지보수를 위해서 일부러 뻔한 리터럴 연산을 풀어쓰는 경우도 있다.

  풀어쓰더라도 컴파일러에 의해 미리 계산되기 때문에 실행 시 성능차이는 없다.

 

 ex)

컴파일 전의 코드 컴파일 후의 코드
char c2 = 'a'+1;
int sec = 60 * 60 *24;
char c2 = 'b';
int sec = 86400;

char c2 = c1 + 1; → char c2 = (char)(c1+1); // 변수 간의 연산

 

# 버림 / 반올림

- 버림

ex)

class OperatorEx16{
		public static void main(String[] args) {
			float pi = 3.141592f;
			float shortPi = (int)(pi*1000) / 1000f;
			System.out.println(shortPi); // 결과 : 3.141
		}
	}

int형 간의 나눔셈을 수행하면 결과는 int가 된다.(float나 double 아님 주의)

또한 나눗셈의 결과를 반올림 하는 것이 아니라 버림한다.

 

- 반올림

ex)

class OperatorEx17{
		public static void main(String[] args) {
			double pi = 3.141592f;
			double shortPi = (int)(pi * 1000 + 0.5) / 1000.0;
			System.out.println(shortPi); // 결과 : 3.142
		}
	}

반올림을 위해 0.5를 더해줌

 

- Math.round() : 매개변수로 받은 값을 소수점 첫째자리에서 반올림 하고 그 결과를 정수로 돌려주는 메소드

                     위의 반올림 방법보다 더 간단히 처리할 수 있다.

ex)

class OperatorEx18{
		public static void main(String[] args) {
			double pi = 3.141592;
			double shortPi = Math.round(pi * 1000) / 1000.0;
			System.out.println(shortPi); // 결과 : 3.142
		}
	}

 

★ Math.round() : 반올림

    Math.ceil() : 올림 (천장)

    Math.floor() : 내림 (바닥)

 

   위의 세 가지 메소드들은 무조건 소수점 이하가 있는 경우 해당 메소드를 실행한다.

   실제 코딩 시 많이 사용하므로 암기해두자!

 

Q. 사용자로 부터 문자하나를 입력받아, 

     입력받은 값이 숫자이면, '숫자', 소문자이면, '소문자', 대문자이면 '대문자'라고 출력하자. (자바의 정석 p.117)

Scanner scanner = new Scanner(System.in);
char ch = ' ';
System.out.println("문자를 하나 입력하세요.>");

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

A.

import java.util.Scanner;

public class Operator {
	public static void main(String[] args) {
	Scanner scanner = new Scanner(System.in);
	char ch = ' ';
	System.out.println("문자를 하나 입력하세요.>");
	while(true) {
	String input = scanner.nextLine();
	ch = input.charAt(0);
	
	if(input.length() == 1) {
		scanner.close();
		break;
	}
	else {
		System.out.println("한 글자만 입력해주세요.");
	  	System.out.println("다시 입력해주세요.");
		}
	}		
	if('0' <= ch && ch <= '9')
		System.out.println("숫자");
	else if('a'<= ch && ch <='z')
		System.out.println("소문자");
	else if ('A'<=ch && ch <='Z')
		System.out.println("대문자");
	scanner.close();
	}
}

 

3.2 나머지 연산자 (%)

     왼쪽의 피연산자를 오른쪽 피연산자로 나누고 난 나머지 값을 결과로 반환하는 연산자

     나누는 수로 음수도 허용한다.

     따라서 피연산자의 부호를 모두 무시하고,

     나머지 연산을 한 결과에 왼쪽 피연산자(나눠지는 수)의 부호를 붙이면 된다.

 

4. 비교 연산자

4.2 등가비교 연산자( ==, !=)

- == : 두 값이 같으면 true, 아니면 false

- != : 두 값이 다르면 true, 아니면 false

 

// Tip : >=와 같이 두 개의 기호로 이루어진 연산자는

          기호의 순서 바꾸는 것과 중간에 공백이 있는 것을 허용하지 않는다.

 

ex) 10.0 = 10.0f의 결과는 false인데 

     이는 정수형과 달리 실수형은 근사값으로 저장되므로 오차가 발생할 수 있기 때문이다. 

 

# 문자열의 비교 (equals())

    equals 메소드는 비교하고자 하는 대상의 내용 자체를 비교

    == 연산자는 비교하고자 하는 대상의 주소값을 비교

 

5. 논리연산자

5.1 논리연산자( &&, ||, !)

- || (OR 결합) : 피연산자 중 어느 한 쪽만 true이면 true를 결과로 얻는다.

- && (AND 결합) : 피연산자 양쪽 모두 true여야 true를 결과로 얻는다.

 

# 효율적인 연산 - Short Circuit Evaluation(SCE, 숏 서킷 연산 :  연산생략)

  AND 혹은 OR 의 연산에 있어서 결과가 확실하게 예측이 되었을 때

  뒤에 나머지 연산을 실행하지 않고 답을 내버리는 경우를 의미

 

# 논리 부정 연산자(!)

   !true = false

 

5.2 비트연산자( &, |, ^, ~, <<, >> )

- | (OR연산자) : 피연산자 중 한 쪽의 값이 1이면, 1을 결과로 얻는다. 그 외에는 0을 얻는다.

- & (AND연산자) : 피연산자 양 쪽이 모두 1이어야만 1을 결과로 얻는다. 그 외에는 0을 얻는다.

- ^ (XOR연산자) : 피연산자의 값이 서로 다를 때만 1을 결과로 얻는다. 같을 때는 0을 얻는다.

 

Q. 사용자로 부터 int형 정수하나를 입력받아, 그 값을 4byte 이진수 형태로 출력하자. (자바의 정석 p.122)

ex)

10진 정수를 입력하세요. 
10 
2진수 
00000000000000000000000000001010

 

[참고] Integer.toBinaryString(10); 를 이용해보시오.

 

A. 교재 답

class OperatorEx28{
		public static void main(String[] args) {
			int x = 0xAB, y = 0xF;
			
			System.out.printf("x = %#X \t\t%s%n", x, toBinaryString(x));
			System.out.printf("y = %#X \t\t%s%n", y, toBinaryString(y));
			System.out.printf("%#X | %#X = %#X \t%s%n", x, y, x | y, toBinaryString(x | y));
			System.out.printf("%#X & %#X = %#X \t%s%n", x, y, x & y, toBinaryString(x & y));			
			System.out.printf("%#X ^ %#X = %#X \t%s%n", x, y, x ^ y, toBinaryString(x ^ y));
			System.out.printf("%#X ^ %#X ^ %#X = %#X \t%s%n", x, y, y, x ^ y ^ y, toBinaryString(x ^ y ^ y));
		}
			
		static String toBinaryString(int x) {
			String zero = "00000000000000000000000000000000";
			String tmp = zero + Integer.toBinaryString(x);
			return tmp.substring(tmp.length()-32);
		}
}

 

A. 내가 생각한 답

package practice0727;
import java.util.Scanner;

public class Operator2 {
	public static void main(String[] args) {
	Scanner scanner = new Scanner(System.in);
	System.out.println("10진 정수를 하나 입력하세요.>");
	int input = scanner.nextInt();
	String temp = "";
	String binary = Integer.toBinaryString(input);
    
	for (int i = 0; i < 32-binary.length(); i++) {
		temp += 0;
	}
    
	temp = temp+binary;
	System.out.println("2진수 :"+temp);
	scanner.close();
	}
}	

 

 

# 비트 전환 연산자 (~)

   피연산자를 2진수로 표현했을 때, 0은 1로 1은 0으로 바꾼다.

   논리부정 연산자(!)와 유사하다.

 

# 쉬프트연산자(<<, >>)

   피연산자의 각 자리(2진수로 표현했을 때)를 '오른쪽(>>)' 또는 '왼쪽(<<)'으로 이동(shift)한다.

   ex) 8<<2 : 왼쪽 피연산자인 10진수 8의 2진수를 왼쪽으로 2자리 이동한다.

                 빈칸은 0으로 채운다.

       8>>2 : 10진수 8의 2진수를 오른쪽으로 2자리 이동한다.

                빈칸은 음수인 경우 1, 양수는 0으로 채운다.

 

6. 그 외의 연산자

6.1 조건연산자 ?: (= 삼항연산자)

     자바 내 유일한 삼항연산자이다.

 조건식? 식1 : 식2
        (참)   (거짓)

     ex) absX = x >=0? x : -x;

 

6.2 대입연산자 (=, op=)

    변수와 같은 저장공간에 값 또는 수식의 연산결과를 저장하는데 사용

 

# 복합대입연산자

728x90