3주차 항해일지 - 연산자

김종하·2020년 11월 27일
1

Live Study - WHITESHIP

목록 보기
4/14

목차
1. 산술 연산자
2. 비트 연산자
3. 관계 연산자
4. 논리 연산자
5. instanceof
6. assignment(=) operator
7. 화살표(->) 연산자
8. 3항 연산자
9. 연산자 우선 순위
10. (optional) Java 13. switch 연산자

1. 산술 연산자

+ 더하기연산자
- 빼기연산자
* 곱하기연산자
/ 나누기연산자
% 나머지연산자
++ 증가연산자
-- 감소연산자

산술 연산자는 두개의 피연산자를 사용하여 계산을 수행하는 함수를 의미한다.
기본적인 +, -, *, / 같은 사칙연산을 포함하여 %(나머지 연산,Modulus) 과 ++(Increment), --(Decrement)와 같은 감소연산자가 바로 산술 연산자 이다. 다음 코드로 일반적으로 잘 사용하지 않는 나머지 연산과 증감연산을 살펴보자.

그런데, 과연 컴퓨터는 사칙연산을 어떤방식으로 수행할까?

ALU를 통한 컴퓨터의 연산

컴퓨터는 ALU라는 장치를 통해 연산을 수행한다. ALU는 가산기와 누산기등의 회로로 구성되어 있는데 이를 통해 덧셈이 가능해진다. ALU를 통해 연산을 수행함으로 덧셈을 활용해 모든 사칙연산을 수행하는데, 뺄셈은 양수와 음수의 덧셈으로 구할 수 있고, 곱셈은 덧셈 반복으로, 나눗셈은 아까전에 얘기했던 뺼셈의 반복으로 구할 수 있다.
(참고. 감산기와 같은 회로로 뺼셈을 할 수 도있지만, 회로의 복잡성 때문에 가격이 훨씬 비싼걸로 알고 있다.)

이제, 우리는 음수의 데이터를 표현하는 방법을 생각해보아야 한다.

컴퓨터는 모든 데이터를 0과 1 로 표현한다. 그 말은, 사람처럼 -부호를 통해 음수를 표현할 수 없음을 의미한다. 가장 쉽게 양수와 음수를 표현할 방법을 생각해보면 특정 비트를 부호비트로 두고 해당비트가 0이면 양수 1이면 음수 로 표현하기로 약속하는 방법이 있다. 그래서 실제로, MSB(최상위비트)를 부호비트로 사용하는 경우가 많다.
우리가 자주 사용하는 int 데이터형도 4바이트, 즉 32비트의 데이터 크기를 가지지만 2의 32승인 4,294,967,296‬ 이 아닌 2의 31승에 1을 뺀2,147,483,647 까지 밖에 표현하지 못한다. 1비트가 부호비트로 사용되어 -2,147,483,648 과 0 을 표현해야하기 때문이다.
부호비트를 사용해서 음수를 표현하게 된 것 까지는 좋지만, 연산에서 문제가 발생한다.
예를들어 2진수로 5는 0101 이고 -2는 1010 이다. 이 때 이둘을 더하면
5 + (-2) 는 3이 나와야하지만
0101
1010
을 더하면 1111 이되어 -7 을 의미하게 된다. 그래서 음수를 표현하기 위해 2의 보수를 사용하게 된다.
-2를 2의 보수를 사용해 나타내면, -2의 양수값인 0010의 1의 보수를 구한다(0은 1로 1은 0으로) 1101 그리고 여기에 1을 더한다 1110
1110 은 -2를 표현하게 되고 5 + (-2)는 다음식이 된다.
0101
1110
0011 => 3
이러한 연산에서 표현범위를 벗어나는 값들은 무시하게되는데, 이로인해서 특정 값들의 연산에서는 overflow가 발생해 원하지 않는 값이 결과로 나오기도한다.

2. 비트 연산자

&(AND)
|(OR)
^(XOR)
~(NOT)
<<(Left Shift)
>>(right Shift)
>>>(right Shift)

비트 연산자에는 &(AND), |(OR), ^(XOR), ~(NOT), <<(Left Shift), >>(right Shift), >>>(right Shift)와 같은 연산자들이 있다. 코드를 통해 다음 연산들을 확인해 보자.
더불어, >> 연산자와 >>> 연산자는 비트를 이동할때 MSB 값으로 채울지, 무조건 0으로 채울지에 대한 차이가 있는데 >>연산은 MSB값으로, >>>은 0으로 채우게 된다.

3. 관계 연산자

> 크다
< 작다
>= 크거나 같다
<= 작거나 같다
== 같다
!= 같지않다

관계 연산자는 두 피연산자의 관계를 표현하는 연산자이다. 예를들어, A가 B보다 크다와 같이 관계를 나타내는데 >(크다), <(작다), >=(크거나 같다), <=(작거나 같다), ==(같다), !=(같지않다)와 같은 연산자가 있다. 코드를 통해 확인해 보자.

4. 논리 연산자

& (AND)
| (OR)
^ (XOR)
! (NOT)
&& (AND)
|| (OR)

논리연산자는 비트연산자와 유사하지만 논리식(boolean)에서 사용되는 연산자이다. 코드를 통해 확인해 보도록 하자.

그렇다면 & 와 && , | 와 ||의 차이는 무엇일까
여러 논리 조건이 동시에 있을때를 생각해보자

if ( false & true ) 
if ( false && true ) 

다음과 같은 조건이 있다고 생각을 해보자. 첫 번째 조건이 false 이면 뒤의 조건들을 생각하지 않아도 해당 조건은 false 가 된다.
그런데 이 때 & 연산자를 사용하면 결과를 첫 번째 조건을 통해서 이미 알았다 하더라도 두번째 조건도 확인하는 과정을 거치고, && 연산을 사용하면 첫 번째 조건에서 해당 논리식의 값을 유추했다면 뒤의 조건들은 확인하지 않는다.

즉, 연산속도를 생각한다면 && 이나 || 이 & 와 | 보다 더 빠른 속도를 가지게 될 것 이다.

5. instanceof

특정 Class 구조로 메모리에 할당된 실체를 해당 Class의 인스턴스라고 부르는데, 이를 통해 instanceof 가 어떤 연산자인가에 대해 유추해 볼 수 있다.
instanceof를 통해 특정 변수가 특정 class 타입인지를 확인할 수 있다.

해당 연산자를 통해 상속관계를 확인해, 타입캐스팅이 가능한지에 대해 판단할 수 있다.

6. assignment(=) operator

대입연산자 혹은 할당연산자라 칭해지는 = 는 오른쪽 피연산자의 값을 왼쪽피연산자에 대입(할당)한다 단순한 = 연산자 이외에도 사칙 연산과 대입 연산을 함께 수행하는 복합 대입 연산자도 있다.

변수 += 값 -> 변수의 기존 값에 + 값을 더한 결과를 변수에 대입
변수 -= 값
변수 *= 값
변수 /= 값
변수 *= 값
변수 &= 값
...

단, referece 타입의 경우 해당 객체의 주소값이 변수에 할당되게 된다.

7. 화살표(->) 연산자

함수형 프로그래밍을 위해 자바 8 부터 도입된 람다식에서 사용되는 -> 연산자는 왼쪽 피연산자에 매개변수가 들어가고 오른쪽 피연산자에 구현부가 들어간다

( parameters ) -> expression body // 인자가 여러개 이고 하나의 문장으로 구성
( parameters ) -> { expression body } // 인자가 여러개 이고 여러 문장으로 구성
() -> { expression body } // 인자가 없고 여러 문장으로 구성
() -> expression body // 인자가 없고 하나의 문장으로 구성

추후에, 함수형 프로그래밍과 람다식에대해서 더 공부해보도록 하자

8. 3항 연산자

Condition Operator 라고도 불리는 3항 연산자는 간단한 분기문을 처리할때 유용한 연산자인데 condition ? A : B 와같이 표현될 수 있다.
여기서 condition 은 true, false 를 반환하는 조건식이고 condition 이 true 라면 A를 false 라면 B를 반환하게 된다.

9. 연산자 우선 순위

여러 연산자들이 한 코드 내에 있다면 어떤 연산자가 먼저 연산되어야 할 것인가에 대한 기준이 필요하다. 다음 코드로 연산자의 우선순위를 살펴보자.

출처: https://medium.com/@katekim720/%EC%97%B0%EC%82%B0%EC%9E%90%EB%B6%80%ED%84%B0-%EC%A1%B0%EA%B1%B4-%EB%B0%98%EB%B3%B5%EB%AC%B8%EA%B9%8C%EC%A7%80-3d5cec6513d4
, 이것이 자바다 | 신용권의 Java 프로그래밍 정복_1

10. (optional) Java 13. switch 연산자

Switch 연산자는 변수의 값에 따라 분기시키는 연산자이다
다중 if - else 문보다 가독성이 좋아 가능한 경우 switch 문을 사용하면 코드를 이해하기 쉬운 장점이 있다. 또한, if - else 문의 경우 위에서 순서대로 진행되는 반면 switch 문으로 분기할 경우 해당 값에 따른 코드로 바로 분기됨으로 성능에도 이점이 있는 것으로 알고 있다.
그리고 switch 문에는 primitive 타입과 primitive wrapper 클래스, enum과 String 클래스를 사용할 수 있다.

스터디 깃헙주소 : https://github.com/whiteship/live-study/issues/3

0개의 댓글