프로그래밍/자바(JAVA)

[자바를 다루는 기술 Vol.2] Session3 자바에서 사용하는 연산자 & 연산

aSpring 2021. 4. 27. 08:14
728x90
728x90

2021.04.26 - [프로그래밍/자바(JAVA)] - [자바를 다루는 기술 Vol.1] Session2 변수와 데이터형

2021.04.27 - [프로그래밍/자바(JAVA)] - [메모리 구조] 자바(JAVA)의 메모리 구조(정리 중)

 

21.04.27(화)~

 

<진법 변환 : 10진수 -> 2/8/16 진수로 변환>

Integer.toBinaryString(6);   // 매개변수로 정수 입력 -> 2진수로 표기해줌
Integer.toOctalString(6);    // 정수 매개변수 -> 8진수로 표기
Integer.toHexString(6); 	 // 정수 매개변수 -> 16 진수로 표기

 

<진법 변환 : 음의 10진수 -> 2진수>

1. 음수 표현을 하기 위해 필요한 개념 : ① 절댓값 ② 1의 보수 ③ 2의 보수

2. 양/음수의 표현은 최상위 비트(가장 왼쪽 비트, MSB)로 부호를 표현 -> 0 : 양수, 1 : 음수

3. 컴퓨터의 음수 표현

  1) 양수 표현에 부호만 바꾸기

      ex) +4 : 0000 0100

      ex) -4 : 1000 0100

  2) 1의 보수로 나타내기(0 -> 1, 1 -> 0)

      ex) +4 : 0000 0100      

      ex) -4 : 1111 1011

  3) 2의 보수로 나타내기(1의 보수로 변환 후 +1)

      ex) +4 : 0000 0100    (10진수 4의 2진법 표현)

      ex) -4 : 1111 1011    (1의 보수)

                           +1

      ex) -4 : 1111 1100    (2의 보수)

-> 1, 2번은 문제가 발생 : 컴퓨터에서는 2의 보수 표현 방법을 사용

 

- 책의 예제에서 나오는 10진수 -5를 2진수로 나타내기!

① 절댓값 : 5 -> 0000 0101

② 1의 보수 :     1111 1010

③ 2의 보수 :     1111 1011(2)  == -5(10)

(참고 : iscm983.tistory.com/18 )

 


 

1. 선언한 데이터를 어떻게 연산할지 알아보기
2. 연산자에 대한 이해

 

01 기본 연산자

대입 연산자

: 변수에 값이나 연산 결과를 저장하는 연산자( = )

 

대입 연산자 종류

기호 연산자 사용법 설명
= a = 3 변수명 a에 변수값 3을 대입한다.
+= a += b a = a+b
변수 a에 b값을 더한 후
그 값을 a에 대입
-= a -= b a = a - b
*= a *= b a = a * b
/= a /= b a = a / b

+-, -=와 같은 연산자 사용 -> 실제로 풀어 쓴 연산자보다 좀더 빠른 연산이 이뤄지나 코드의 가독성이 떨어지는 단점

 

사칙 연산을 위한 산술 연산자

산술 연산자 : 가장 기본이 되는 연산자

사칙 연산자 : + 덧셈, - 뺄셈, * 곱셈, / 나눗셈, % 나머지

 

package Session1.com.gilbut.chapter3;
// p.072 사칙연산을 위한 산술 연산자
public class ModOperation {

	public static void main(String[] args) {
		int a = 100;
		int b = 7;
		
		System.out.println("quotient : " + a / b); // 나눗셈
		System.out.println("remainder : " + a % b); // 나머지
	}
}
quotient : 14
remainder : 2

 

[변수형에 따른 연산값의 변화]

a / b 연산을 했음에도 결과값이 소수점 이하 자릿수 없이 정수로 나옴

-> int형끼리 연산 -> 결과값도 int형(데이터 손실 현상으로 소수점 아래의 데이터 표기X)

 

int형 변수와 float형 변수끼리 사칙연산 시

-> int형 변수가 float형 변수로 형 변환 -> 나눗셈 진행

-> 결과값은 float이 됨

 

<JVM : 산술 연산자를 사용한 결과에 대한 형 변환 규칙>

- 피연산자들의 변수형이 서로 다르면 데이터 값의 범위가 큰 변수형으로 둘 다 형 변환된다.

- int형보다 작은 크기의 변수형들은 int로 형 변환된다.

 

간결한 코드 작성을 위한 단항 연산자(unary operator)

피연산자 : 연산의 대상이 되는 변수

 

단항 연산자 : 피연산자가 하나인 연산자

  ex) ++price -> 연산자 ++, 피연산자 price

이항 연산자 : 피연산자가 2개

  ex) 3 + 5 -> 연산자 +, 피연산자 3, 5

삼항 연산자 : 피연산자가 3개

 

단항 연산자 종류

  연산자 설명
증감 연산자 ++ 피연산자의 변수값을 1 증가시킴
i++, --i
-- 피연산자의 변수값을 1 감소시킴
i--, --i

 

단항 연산자 : 연산자와 변수를 붙여서 사용

- 숫자형 byte, short, char, int, long, float, double형 변수에 사용 가능

 

- 전위형 : ++i 처럼 연산자가 피연산자의 앞에 위치 -> 변수가 사용되기 전에 증감 연산 실시

- 후위형 : i-- 처럼 연산자가 피연산자의 뒤에 위치 -> 변수가 사용된 이후 증감 연산 실시

-> 차이 : 연산자의 실행 시점에 따라 결정됨 -> 해당 연산의 실행 시점이 프로그램에서 변수가 참조되고 난 후냐 혹은 참조되기 전이냐에 따라 결정됨

-> 이항 연산자보다 속도가 빠르고 보다 간단하게 코드를 구성할 수 있음

 

package Session1.com.gilbut.chapter3;
// p.074
public class UnaryOperator {
	public static void main(String[] args) {
		int vluAfter = 0;
		long vluBefore = 0;
		char chrAfter = 'A';
		
		System.out.println("First reference : " + vluAfter++); // 0
		System.out.println("First reference : " + --vluBefore); // -1
		System.out.println("First reference : " + chrAfter++); // A
		
		System.out.println("Second reference : " + vluAfter); // 1
		System.out.println("Second reference : " + vluBefore); // -1
		System.out.println("Second reference : " + chrAfter); // B
	}
}

 

다양한 비교를 위한 비교 연산자

- 피연산자를 비요하기 위해 사용 : 결과값은 true/false

- 조건문, 반복문에서 많이 사용됨

수식 예시 설명
> a > b a가 b보다 크면 true, 아니면 false
< a < b a가 b보다 작으면 ture, 아니면 false
>= a >= b a가 b보다 크거나 같으면 true, 아니면 false
<=  a <= b a가 b보다 작거나 같으면 true, 아니면 false
== a == b a와 b가 같으면 true, 아니면 false
!= a != b a와 b가 다르면 true, 아니면 false

 

02 논리 연산자와 비트 연산자

true/false 판단을 위한 논리 연산자

- 논리 연산자 : true 또는 false 값을 갖는 boolean형의 피연산자들을 판단 -> 그 결과값을 true/false로 반환

- 비교 연산자와 마찬가지로 논리 연산자들도 조건문/반복문에서 많이 사용

연산자 기호 설명 사용 예
NOT 연산자 ! 한 개의 피연산자 필요하며
boolean 변수 혹은 데이터에만 사용 가능
연산자의 위치는 전위형
!isWork, !(true);
AND 연산자 && 두 개의 피연산자 필요
피연산자들은 boolean 변수 혹은 데이터에만 사용 가능
isWorking && isNull
OR 연산자 || 두 개의 피연산자 필요
피연산자들은 boolean 변수 혹은 데이터에만 사용 가능
isWorking || isNull

 

1. NOT 연산자 : 부정 연산자, !

- 사용 가능한 변수형 : 오직 boolean형

- 동작 : 1bit로 구성된 boolean 연산자의 값을 바꾸는 연산 -> 스위치(switch) 동작 수행

- 반드시 전위형으로 사용

package Session1.com.gilbut.chapter3;
// p.077
public class NotOperation {

	public static void main(String[] args) {
		boolean isWorking = false;
		
		isWorking = !isWorking; // false 값을 가진 isWorking 변수에 NOT 연산 후 다시 isWorking 변수에 대입
		System.out.println("isWorking : " + isWorking); // true
		isWorking = !isWorking;
		System.out.println("isWorking : " + isWorking); // false
	}
}

 

 

 

2. AND 연산자 : 2항 연산자(피연산자 2개)

- 피연산자가 둘 다 true이면 -> true

- 둘 중 하나라도 false이면 -> false

- AND 연산자 진리표

변수명 a 변수명 b a && b 연산 결과
true true true
true false false
false true false
false false false

 

package Session1.com.gilbut.chapter3;

public class HelloWorld {

	public static void main(String[] args) {
		if(args != null && args.length > 0) { // Run Configration 설정해야 함
			for(String arg : args) {
				System.out.println(arg);
			}
		}
	}
}
Hello
World!

 

3. OR 연산자 : 2항 연산자

- 두 개의 피연산자 중 하나라도 true이면 true 반환

- OR 연산자의 진리표

변수명 a 변수명 b a || b 연산 결과
true true true
true false true
false true true
false false false

 

(args != null && args.length > 0)

!(args == null || args.length <= 0)

->  둘 다 같은 결과 반환

 

2진수 연산을 위한 비트 연산자

- byte, short, int, char 변수형에 대해 사용 가능한 연산자

- 비트 연산자와 관련된 모든 연산 -> 2진수 체계에서 처리됨

- 비트 연산자 사용 이유 : 보다 빠른 연산 가능(컴퓨터 내부 프로세스는 2진수로 처리되고 있음)

연산자 기호 설명 사용예
비트 NOT 연산자 ~ 2진수의 각 자릿수에 대해 NOT 연산 수행
피연산자가 하나 -> 단항 연산자처럼 사용
~0B001
비트 AND 연산자 & 2진법으로 표시된 두 개의 피연산자가 필요
2진법 각 자릿수에 대해 AND 연산 수행
OB001 & OB010
비트 OR 연산자 | 2진법으로 표시된 두 개의 피연산자가 필요
2진법 각 자릿수에 대해 NOT 연산 수행
OB001 | OB010
비트 XOR 연산자 ^ 2진법으로 표시된 두 개의 피연산자가 필요
2진법 각 자릿수에 대해 XOR 연산 수행
피연산자의 두 값이 서로 다를 때만 true 반환
0B001^0B010

 

1. 비트 NOT 연산자 == 비트 보수 연산자

- 2진수의 각 자릿수마다 NOT 연산 처리 ->

~0B0 == 0B1

~0B01 -> 0B10

(0B는 2진수라고 선언하는 리터럴)

package Session1.com.gilbut.chapter3;
// p.081 비트 NOT 연산자
public class bitNotOperation {

	public static void main(String[] args) {
		int i = 10;
		System.out.println("Variable i (Decimal) : " + i); // 10진수 i
		System.out.println("Variable i (Binary) : " + Integer.toBinaryString(i)); // 2진수로 변환한 i
		
		i = ~i; // NOT 연산
		System.out.println("Variable i (Decimal) : " + i); // 10진수 i
		System.out.println("Variable i (Binary) : " + Integer.toBinaryString(i)); // 2진수 i
	}
}
Variable i (Decimal) : 10
Variable i (Binary) : 1010
Variable i (Decimal) : -11
Variable i (Binary) : 11111111111111111111111111110101

-> int 변수형의 메모리 크기 : 32bit

00000000000000000000000000001010 (10진수 10의 2진수 표현) -> 보수 연산

11111111111111111111111111110101

(10진수 10의 2진수 표현 -> 보수 연산 -> 비트의 보수 : -11 -> 정수의 보수 : -11+1 = -10)

 

2. 비트 AND, OR, XOR 연산자

- XOR 연산자 : 피연산자의 각 자리수가 서로 다를 경우 true 혹은 1 반환, 서로 같은 경우 false 혹은 0 반환

- 비트 AND, OR, XOR 연산자의 진리표

변수가 갖는 경우의 수 연산 결과
X Y X & Y
(둘 다 1이어야 1)
X | Y
(둘 중 하나만
1이어도 1)
X ^ Y
(두개가 서로 다른 값이면 1)
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0

 

package Session1.com.gilbut.chapter3;
// p.082 비트연산자
public class bitOperation {

	public static void main(String[] args) {
		int b1 = 0B0010; // 0B -> 2진수 리터럴
		int b2 = 0B0101;
		int b3 = 0B1111;
		
		int rtAndOp = b1 & b3; // 비트 AND 연산자
		int rtOrOp = b1 | b2; // 비트 OR 연산자
		int rtXorOp = b1 ^ b3; // 비트 XOR 연산자
		
		System.out.println("b1 AND b3 : " + Integer.toBinaryString(rtAndOp)); // 0010
		System.out.println("b1 OR b2 : " + Integer.toBinaryString(rtOrOp)); // 0111
		System.out.println("b1 XOR b3 : " + Integer.toBinaryString(rtXorOp)); // 1101
	}
}
b1 AND b3 : 10
b1 OR b2 : 111
b1 XOR b3 : 1101

 

03 시프트 연산자와 3항 연산자

시프트 연산자 : 정수형 변수에서만 사용 가능

- 이진법으로 표기된 데이터의 자리를 이동시키는 역할

-  이동 방향에 따라 '<<' 혹은 '>>'으로 표기

- 사용법 : a >> 2의 형태로 사용

       피연산자  시프트

  (대상데이터)  (이동하는 횟수)  

 

ex) 6 << 3

-> 10진수 6을 2진수로 변환 : 0B0110 -> 왼쪽으로 3칸 이동 0B0110000 -> 10진수로 변환 : 48

-> 쉽게 암산하기 6 * (2의 3승) = 6 * 8 = 48

 

연산자 설명
<< 연산자 데이터를 왼쪽으로 지정한 숫자만큼 자릿수를 점프
점프하고 남은 자릿수는 피연산자가 양수인 경우 0으로 채우고
피연산자가 음수인 경우 1로 채움
음수, 양수를 의미하는 맨 앞의 비트는 연산에 관여하지 않음
연산 결과를 10진수로 바꾸면 -> 피연산자 * (2^점프한 수)
>> 연산자 데이터를 오른쪽으로 지정한 숫자만큼 자릿수를 점프
점프하고 남은 자릿수는 피연산자가 양수인 경우 0으로 채우고
피연산자가 음수인 경우 1로 채움
음수, 양수를 의미하는 맨 앞의 비트는 연산에 관여하지 않음
연산 결과를 10진수로 바꾸면 -> 피연산자 / (2^점프한 수)
>>> 연산자 데이터를 오른쪽으로 이동
점프하고 남은 자릿수는 부호에 상관없이 0으로 채움
항상 양수를 유지 -> unsigned shift operator이다
                          (부호 비트가 필요 없음)

 

 

package Session1.com.gilbut.chapter3;
// p.085
public class ShiftOperation {

	public static void main(String[] args) {
		int x = -5;
		int y = 6;
		
		int rt1 = x << 4; // -5에 대한 left 시프트 연산
		int rt2 = x >> 2; // -5에 대한 right 시프트 연산
		int rt3 = y << 3; // 6에 대한 left 시프트 연산
		int rt4 = y >> 1; // 6에 대한 right 시프트 연산
		int rt5 = y >>> 3; // 6에 대한 unsigned right 시프트 연산
		
		System.out.println("Binary x : " + Integer.toBinaryString(x)); // -5의 이진수 표기 : 11111111111111111111111111111011
		System.out.println("Binary y : " + Integer.toBinaryString(y)); // 6의 이진수 표기 : 110
		
		System.out.println("left : " + rt1 + ", " + Integer.toBinaryString(rt1)); // -80, 11111111111111111111111110110000
		System.out.println("right : " + rt2 + ", " + Integer.toBinaryString(rt2)); // -2, 11111111111111111111111111111110
		System.out.println("left : " + rt3 + ", " + Integer.toBinaryString(rt3)); // 48, 110000
		System.out.println("right : " + rt4 + ", " + Integer.toBinaryString(rt4)); // 3, 11
		System.out.println("unsigned right : " + rt5 + ", " + Integer.toBinaryString(rt5)); // 0, 0
	}
}
Binary x : 11111111111111111111111111111011
Binary y : 110
left : -80, 11111111111111111111111110110000
right : -2, 11111111111111111111111111111110
left : 48, 110000
right : 3, 11
unsigned right : 0, 0

-5(10)     ==  1111 1011(2)

 

-5 << 4  -> -5 * 2의 4승 -> -80(10)

                1111 ~ 10110000

-5 >> 2  -> -5 / 2의 2승 -> 왜 -2지?

        1111 1011(2) -- >>2 --> 1111 1110 -- 10진수로 변환하기 --> 1111 1101 -> 0000 0010

        --음수니까--> 1000 0010 -> -2

 

6(10) == 0000 0110(2)

 

6 << 3 -> 6 * 2의 3승 = 6 * 8 = 48

           0000 0110 -- <<3 --> 0011 0000(2) -> 48(10)

 

6 >> 1 -> 6 / 2 = 3

           0000 0011(2) -> 3

 

6 >>> 3  -> 6 / 2의 3승

            0110 -- >>>3 --> 0000(2) -> 0(10)

 

3항 연산자 : 피연산자의 개수가 3개

- 조건 비교 -> 그 결과를 반환하는 연산자

(피연산자1) ? (피연산자2) : (피연산자3) ;

                   true일 때     false일 때

->피연산자1의 결과값은 항상 boolean 값이 나오도록 변수를 설정하거나 연산식을 넣으면 됨

- 3항 연산자를 활용한 예제

3항 연산자 사용예 설명
case 1 boolean isRound = false;
boolean rt = (isRound) ? true : false;
isRound의 변숫값에 따라서 변수 rt에 Boolean 값이 설정됨
isRound 값이 true이면 rt도 true,
false면 rt도 false
case 2 boolean isEnable = true;
int rt = (isEnable) ? 1 : 2;
isEnable의 변수값이 true이면 rt는 1, false이면 rt는 2
case 3 int a = 3;
boolean rt = (a > 0) ? false : true ;
a가 4를 초과하면 rt는 false, 그렇지 않으면 rt는 true
case 4 int a = 3;
int rest = (a > 0) ? (a % 2) : 0;
a가 0을 초과하면 rest에는 a%2의 결과 값을, false이면 0이 입력됨
package Session1.com.gilbut.chapter3;
// p.087 3항 연산자
public class TenaryOperator {

	public static void main(String[] args) {
		
		// 2개의 매개변수를 받았는지 검사하는 구문
		if(args == null | args.length != 2) { // 매개변수가 null이거나 개수가 2개가 아닐 때
			System.out.println("help : hava TenaryOperator number1 number2"); // 도움말 출력
			return; // 프로그램 종료
		}
		
		int a = Integer.parseInt(args[0]);
		int b = Integer.parseInt(args[1]);
		int c = (a > b) ? (a - b) : (b - a); // if-else 구문과 비슷함
		
        package Session1.com.gilbut.chapter3;
// p.087 3항 연산자
public class TenaryOperator {

	public static void main(String[] args) {
		// java TenaryOperator 3 12
		
		if(args == null | args.length != 2) {
			System.out.println("help : java TenaryOperator number1 number2");;
			return;
		}
		
		int a = Integer.parseInt(args[0]);
		int b = Integer.parseInt(args[1]);
		int c = (a > b) ? (a - b) : (b - a); // if-else 구문과 비슷함
		
		System.out.println((a> b ) ? "A > B" : "B >= A");
		System.out.println("difference : " + c);
	}
}

		System.out.println("difference : " + c);
	}
}
B >= A
difference : 9

- 매개변수로 3과 12를 입력한 경우!

04 String을 사용한 기본 문자열 연산

문자열 연산을 위한 기본 메소드

문자열을 비교하는 방법

특정 문자열의 위치 파악

문자열로 형 변환하는 방법

특정 형식으로 문자열 포매팅하는 법

포맷 지시자

[Java doc 활용]

728x90
728x90