연산자(Operator)

Agnes Park·2022년 1월 23일
1

JAVA

목록 보기
10/34

1. 연산자 관련 용어

연산 Operation
연산자 Operator
피연산자 Operand

  • 피연산자의 개수에 따라 아래와 같이 구분된다.
    • 이항연산자(binary operator) : 피연산자가 2개인 연산자 ex) 2 + 3
    • 단항연산자(unary operator) : 피연산자가 1개인 연산자 ex) -4
    • 삼항연산자(ternary operator) : 피연산자가 3개인 연산자

2. 연산자의 특징

  • 연산자는 연산을 수행하기 전에 피연산자의 타입을 일치시키려 한다.
  • 피연산자의 타입에 따라 수행하는 연산이 달라지는 연산자들도 있다 (ex: + )
  • 모든 연산은 연산의 결과값을 리턴한다 (어떠한 '값'인지?, 어떤 '타입'인지? 주목)
  • 관례적으로 이항연산자는 피연산자와 연산자 간에 한칸씩(space) 띄어주는게 좋다
  • 단항연산자는 피연산자와 연산자를 붙여주는게 일반적이다

3. 연산자의 종류

  • 대입 연산자 assignment operator : '='
    -> 등호(=) 오른쪽의 값을 왼쪽에 대입(저장)
  • 산술 연산자 arithmetic operator : +, -, *, /, %
public class Operator01Main {

	public static void main(String[] args) {
		System.out.println("연산자(Operator) 01");
		
		System.out.println("\n====================");
		System.out.println("[1] 대입 연산자 : = (assignment operator)");
		// 등호(=) 오른쪽의 값을 왼쪽에 대입(저장)
		int num = 123;
		
		// 대입연산자도 연산자다! 따라서
		// 연산의 결과값이 있다.  대입된 값을 결과값으로 리턴함
		int num5;
		int num6;
		System.out.println("num5: " + (num5 = 100));	// 바로 대입 가능. 좋은 코드는 아님
		
		num6 = num5 = 300;	// 대입연산자의 방향: 좌결합성 (오->왼 순으로 대입) / 산술연산자는 우결합성
		System.out.println("num5: " + num5);
		System.out.println("num6: " + num6);
		
		System.out.println("\n====================");
		System.out.println("[2] 산술 연산자: +, -, *, /, % (arithmetic operator)");
		int num1 = 7;
		int num2 = 3;
		int result;
		
		result = num1 - num2;
		System.out.println("뺄셈 결과: " + result);
		result = num1 / num2;
		System.out.println("나누기 결과: " + result);
		result = num1 % num2;
		System.out.println("나머지: " + result);
		
		
		// 나눗셈 연산자(/)가 실수에 사용됐을 경우에는
		// 계산 결과를 실수로 돌려 줌.
		// 실수 / 정수, 정수 / 실수, 실수 /실수 경우에는 결과가 항상 실수형이 됨

		double result2 = 12.1 / 3;
		System.out.println("실수 나누기 결과: " + result2);
		
		// 나머지 연산자(%)
		// 정수 % 정수 = 정수로 값을 돌려 줌.
		// 실수 % 정수, 정수 % 실수, 실수 % 실수 = 몫을 제외한 실수형 나머지를 돌려줌.
		double result3 = 12.1 % 3.0;
		System.out.println("나머지 연산 결과: " + result3); // 자바에서 실수 연산은 약간의 오차가 존재함
		
		// 두 변수 값 바꾸는 방법
		System.out.println();
		int num3 = 100;
		int num4 = 200;
		int temp;
		
		System.out.println("바꾸기전 num3 = " + num3 + " num4 = " + num4);
		temp = num3;
		num3 = num4;
		num4 = temp;
		System.out.println("바꾼후 num3 = " + num3 + " num4 = " + num4);
		
        
		System.out.println("\n프로그램 종료");
	} // end main()

} // end class
  • 복합 대입 연산자 compound assignment operators
    +=, -=, *=, /=, %=, ...
public class Operator02Main {

	public static void main(String[] args) {
		System.out.println("연산자(Operator) 2 - 복합 대입 연산자 compound assignment operators");
		System.out.println("+=, -=, *=, /=, %=, ...");

		int num1 = 10;
		System.out.println("num1 = " + num1);
		// 기존의 변수값에 +1 증가
		num1 = num1 + 1;
		
		System.out.println("num1 = " + num1);
		
		num1 += 1;
		
		System.out.println("num1 = " + num1);
		
		int num2 = 100;
		
		num2 += 20;
		num2 -= 23;
		num2 *= 2;
		System.out.println("num2 = ?" + num2);
		
		
		System.out.println("\n프로그램 종료");
	} // end main()

} // end class
  • 부호연산자(+, -) sign operator
    +: 부호 연산자(수의 부호(양,음)가 바뀌지 않음)
    -: 부호 연산자(수의 부호(양,음)가 바뀜)
public class Operator03Main {

	public static void main(String[] args) {
		System.out.println("연산자 3 - 부호연산자(+, -) sign operator");

		int num1 = -10;
		int num2 = +num1;
		int num3 = -num1;
		System.out.println("num2 = " + num2);
		System.out.println("num3 = " + num3);

		int num4 = 11;
		int num5 = -22;
		int num6 = num4 + -num5;
		System.out.println("num6 = " + num6);

		int num7 = num4 - 	-num5;
		System.out.println("num7 = " + num7);

		System.out.println("\n프로그램 종료");
	} // end main

} // end class
  • 증감 연산자(++, --) Increment / Decrement Operator
    ++변수: 변수의 값을 1 증가시켜서 저장
    --변수: 변수의 값을 1 감소시켜서 저장
  • 증감연산자: prefix(접두사), postfix(접미사)
    접두사(prefix)인 경우에는, 증감(++, --)이 먼저 된 후 다른 연산자가 동작
    접미사(postfix)인 경우에는, 다른 연산자 먼저 실행된 후 증감(++, --)가 동작
public class Operator04Main {

	public static void main(String[] args) {
		System.out.println("연산자 4 - 증감 연산자(++, --) Increment / Decrement Operator");
		
		int num1 = 100;
		++num1;
		System.out.println("num1 = " + num1);
		
		int num2 = 100;
		--num2;
		// num2 = num2 -1 과 동일
		// num2 -= 1과 동일
		System.out.println("num2 = " + num2);
		
		
		System.out.println("\n\n======================");
		System.out.println("증감연산자: prefix(접두사), postfix(접미사)");
		
		int num3 = 100;
		++num3;	// prefit ++
		num3++;	// postfix ++
		System.out.println("num3 = " + num3);
		
		System.out.println();
		int num8 = 10;
		int num9 = --num8 + 5; // -- -> + 순서로 계산 / 14 대입
		
		
		
		// num8 ?
		// num9 ?
		System.out.println("num8 = " + num8);
		System.out.println("num9 = " + num9);
		
		int num10 = 10;
		int num11 = num10-- + 5; // + -> -- 순서로 계산 / 15 대입
		
		System.out.println("num10 = " + num10);
		System.out.println("num11 = " + num11);

		// ★ 실무에서는 위와 같은 코드 작성하지 마세요
		
		int num12 = 10;
		num12++;	// 증감연산자는 수식안에서 사용하지 말고, 단독 사용 ㅊㅊ
		int num13 = num12 + 5;
		
		
		System.out.println("\n프로그램 종료");
	} // end main

} // end class	
  • 관계(비교) 연산자 Equality and Relational Operators
    비교 연산의 결과를 참(true) 또는 거짓(false)으로 리턴하는 연산자
    A < B: A는 B보다 작다
    A > B: A는 B보다 크다
    A >= B: A는 B보다 크거나 같다
    A <= B: A는 B보다 작거나 같다
    A == B: A와 B가 같다.
    A != B: A와 B는 다르다.
public class Operator05Main {

	public static void main(String[] args) {
		System.out.println("연산자 5 - 관계(비교) 연산자   Equality and Relational Operators");
		System.out.println("<, >, <=, >=, ==, !=");

		boolean b = 1.2 <= 2.3;
		System.out.println("b = " + b);
		
		int n1 = 11, n2 = 12;
		boolean b2 = n1 != n2;
		System.out.println("b2 = " + b2);
		
		// 실수 타입에서의 연산결과는 오차가 존재할 수 있다.
		// 절.대.로 비교연산자로 동일여부 체크하면 곤란.
		double d1 = 3.2;
		double d2 = 12.3 / 4.1 + 0.2;	// 3.2????
		
		System.out.println("d1 == d2 : " + (d1 == d2));	// false !!
		
		System.out.println("d1 = " + d1);
		System.out.println("d2 = " + d2);
		
        
		System.out.println("\n프로그램 종료");
	} // end main()
    
} // end class
  • 논리 연산자: &&, ||, !, ^
    A && B: (AND 연산) A와 B가 모두 참일 때만 결과가 true, 나머지는 결과가 false
    A || B: (OR 연산) A나 B 둘 중 하나가 참이면 결과가 true, 둘 다 거짓이면 결과가 false
    !A : (NOT 연산) A가 참이면 결과가 false, 거짓이면 결과가 true
    A ^ B : (XOR 연산)A, B 둘의 논리값이 같으면 false, 다르면 true -> eXclusive OR (배타적 논리합)
public class Operator06Main {

	public static void main(String[] args) {
		System.out.println("연산자 6 - 논리 연산자: &&, ||, !, ^");

		int num1 = 10;
		
		System.out.println(num1 > 0 && num1 < 100);
		System.out.println(num1 > 0 && num1 < 10);
		System.out.println(num1 > 0 || num1 < 10);
		System.out.println(num1 < 0 || num1 < 10);

		System.out.println(num1 > 0);
		System.out.println(!(num1 > 0));
		
		System.out.println(num1 < 0 ^ num1 > 100);
		System.out.println(num1 < 0 ^ num1 < 100);
		
		
		System.out.println("\n 프로그램 종료");
	} // end main ()

} // end class
  • 비트 연산자 (bit-wise operator) - 비트 자리별로 연산?
    a & b: (and) a,b가 모두 1 이면 결과도 1, 그 외에는 0
    a | b: (or) a가 1이거나 또는 b가 1이면 결과는 1, a,b 모두 0일 때만 0
    a ^ b: (xor) a와 b 둘 중 하나만 1이 있는 경우는 1, 그 외에는 0 -> 결국 둘이 같으면 0, 다르면 1
    ~a : (not) a가 1이면 0, a가 0이면 1로 바꿔줌
    -> 일반적인 / 연산보다 비트연산이 더 빠름. 아마 CPU에서 가장 빠른 연산이 비트연산인 일 것(배수, 2의 역승 단위)
public class Operator08Main {

	public static void main(String[] args) {
		System.out.println("연산자 8 - 비트 연산자");
		System.out.println("[1] &(and), |(or), ^(exclusive or), ~(not)");

		byte n1 = 10;	// 0000 1010
		byte n2 = 7;	// 0000 0111
		int result = n1 & n2;
		System.out.println("& 결과 = " + result);
		/*
		 *   0000 1010  n1	// 0을 false, 1을 true로 보기
		 *   0000 0111  n2
		 *  ──────────  &	// & 이기 때문에 둘 다 true인 경우에만 true
		 *   0000 0010 => 2
		 */


		result = n1 | n2;
		System.out.println("| 결과 = " + result);
		/*
		 *   0000 1010  n1
		 *   0000 0111  n2
		 *  ──────────  |
		 *   0000 1111  15
		 */

		result = n1 ^ n2;
		System.out.println("^ 결과 = " + result);
		/*
		 *   0000 1010  n1
		 *   0000 0111  n2
		 *  ──────────  ^
		 *   0000 1101 => 13
		 */


		result = ~n1;
		System.out.println("~ 결과 : " + result);	// 1000 1010으로 수정 -> 비트에서 음수표현 최상위 비트 1로 시작
		
		
		// 음수 정수 표현 참조 : http://tcpschool.com/c/c_refer_negativeNumber
		
		System.out.println("\n\n================");
		System.out.println("비트 이동(shift) 연산자: >>, <<");
		int n3 = 10;
		int result2 = n3 >> 1;	// 비트를 오른쪽(>>)으로 1비트씩 이동 -> 이는 1/2을 의미함. 2칸은 1/4, 3칸은 1/8 (10진수에서 1칸은 1/10) vs 반대로 왼쪽 이동은 2배씩 늘어남
		System.out.println(">> 결과: " + result2);
		
		// 0000 1010  :10
		// ↘↘↘↘ ↘↘↘↘
		// 00000 101  :5 -> 맨 왼쪽 0으로 채워짐

		n2 = 10;
		result2 = n3 << 1;
		System.out.println("<< 결과: " + result2);
		
		
		System.out.println("\n 프로그램 종료");
	} // end main ()

} // end class

4. 산술 연산의 결과 타입

  • 일단 피연산자가 reference type 이면, unbox 후 형변환 수행됨.
  • 그리고 나서 피연산자중 하나라도 double 이면 다른쪽이 double 이 된다.
  • 그렇지 않으면 피연산자중 하나라도 float 이면 다른 쪽이 float 가 된다.
  • 그도 아니면 피연산자중 하나라도 long 이면 다른 쪽을 long 으로 바꾼다.
  • 그도 아니면 양쪽 피연산자 모~ 두 int 로 바꾼다.
  • https://docs.oracle.com/javase/specs/#5.6.2
    When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order, using widening conversion (§5.1.2) to convert operands as necessary:
    If any of the operands is of a reference type, unboxing conversion (§5.1.8) is performed. Then:
    Otherwise, if either operand is of type float, the other is converted to float.
    Otherwise, if either operand is of type long, the other is converted to long.
    Otherwise, both operands are converted to type int.
public class Operator09Main {

	public static void main(String[] args) {
		System.out.println("산술연산의 결과 타입");

		int n1 = 10, n2 = 20;
		int n3 = n1 + n2;
		System.out.println("n3: " + n3);
		
		byte b1 = 10, b2 = 20;
		//byte b3 = b1 + b2;	// byte + byte -> int (에러: cannot be convert from int to byte)
		byte b3 = (byte)(b1 + b2);
		
		long l1 = 10L;
//		int n4 = n1 + l1;	// int + long -> long
		
		float f1 = 1.0f, f2 = 2.0f;
		float f3 = f1 + f2;
		
		double d1 = 1.0, d2 = 2.0;
//		float f4 = f1 + d1;	// float + double -> double
		
		
		// 3000 * 3000 * 3000
		long l2 = 27000000000L;
		
		l2 = 3000 * 3000 * 3000;
		System.out.println("l2: " + l2);	// int로 계산되어서 자료 손실

		
		l2 = 3000L * 3000 * 3000;
		System.out.println("l2: " + l2);
		
		
		System.out.println("\n 프로그램 종료");
	} // end main ()

} // end class

✨Tips

1. TODO의 의미

  • 주석인데 파란색으로 표시됨
  • 아직 작업이 완료되지 않았으므로 채워 넣어야 한다는 의미
  • 심지어, kotlin에서는 TODO 있는 경우 컴파일도 안 된다고 함

2. Source -> Format

  • 가독성이 좋도록 format 띄어쓰기 해주는 기능
  • 단축키 : Ctrl + Shfit + F

3. 워크스페이스와 프로젝트

  • 보통은 하나의 워크스페이스에 한 개의 프로젝트만 진행 (워크스페이스 - JavaWork)

[Workspace의 프로젝트 내보내기 & 가져오기]

  • 프로젝트 내보내기
    • 자바 파일 하나의 압축 파일로 내보내기 옵션
    • 저장 폴더 경로 지정
    • 내보낸 프로젝트 삭제 (체크시: 워크스페이스에서도 물리적으로 완전 삭제)
  • 프로젝트 가져오기
    • Existing Projects into Workspace 옵션 선택
    • Select archive file
    • 또는 Select root directory 및 Copy projects into workspace 클릭

0개의 댓글