상세 컨텐츠

본문 제목

1.5 자료형의 범위는 왜 음수가 더 넓을까? (byte : -128 ~ 127)

How To Java/Java Tutorial

by 카페코더 2020. 2. 19. 18:27

본문

반응형

취업 준비를 하며 복습한다는 마음으로, 이것을 보는 누군가에게 도움이 되었으면 하는 마음으로
Java-Tutoral을 작성해 봅니다. 입문서와 순서가 잘못되었을 수 있고, 제가 아는 정보가 틀렸을 수 있습니다.
이 글에 대한 잘못된 정보나, 오탈자 등 수정해야 할 항목 혹은 추가해야 할 항목은 댓글로 알려주시면 감사하겠습니다.

이 자료가 올라가는 저장소 :
https://github.com/hwk0911/Java-tutorial

 

hwk0911/Java-tutorial

Java tutorial. Contribute to hwk0911/Java-tutorial development by creating an account on GitHub.

github.com

솔직히 제목 정할 때 엄청 고민했습니다.

아 이것도 진짜 필요한 내용인데.... 아 자료형에 넣을까?? 아닌데.. 1번 강의에 넣으면 좋은데 너무 길어..
내가 썼지만 나도 재미없는걸... 그래 1.5장으로 새로 만들자! 그래서 준비한 1장의 번외 1.5장! 

아.. 이거 제목을 뭘로 하지 아.. 최솟값의 절댓값... 아 아냐.. 후..

제목 결정하는데 15분 정도 소모한 것 같습니다. ㅎㅎ

자료형의 범위는 왜 음수가 더 넓을까?

우선 우리는 1장에서 Java의 자료형 (Primitive Type, Reference Type)에 대해 공부하였다.
오늘 주제는 Primitive Type을 기준으로 진행하려 한다.

자료형의 범위가 왜 음수가 양수보다 1 만큼 더 넓은지에 대해 복습하고자 한다.

먼저 결론부터 말씀드리자면, 컴퓨터에서의 음수와 양수의 범위는 같습니다.
-0, +0 중 +0을 채택하였기 때문에 더 넓어보이는 것 입니다.
물론 최대, 최소값의 절대값은 다릅니다.

1. 컴퓨터 연산의 단위

1.1 컴퓨터는 수많은 bit로 이뤄져 있다.

bit : 0 또는 1의 값을 가질 수 있는 단위를 말한다. 전기가 흐르면 1, 전기가 흐르지 않으면 0
즉 컴퓨터에는 오직 두 가지 상태만이 존재한다. 0 or 1
컴퓨터 연산의 최소단위라 할 수 있다.

초등학생 때 읽었던 'why 시리즈 : 컴퓨터'에서는 bit를 설명할 때 전구에 비유하여 설명하였다.
전구는 꺼져있다, 켜져 있다 이 두 상황으로 표현이 가능하다. (밝기 조절이 가능한 전구는 제외한다.)
이때 꺼져있으면 0, 켜져있으면 1이라 가정하였을 때, 전구도 비트와 같은 값을 갖는다.

하지만 여기서 주의 할 점은 bit 가 0과 1을 표현하는것이 아닌 두 가지 상태를 표현하는 것 이다.
이것은 요점이 아니니 넘어가도록 하겠다. 이번 포스팅에서는 bit는 0과 1을 표현한다 가정하고 마저 작성하겠다.

1 bit 는 0 ~ 1의 표현이 가능하고, 2bit 는 0 ~ 3의 표현이 가능하다.
수학에서 배운 2진수와 똑같다! 2진수의 길이가 한칸 이면 0 ~ 1, 두칸 이면 0 ~ 3 이 표현 가능하다.

1.2 Byte는 몇 bit 인가?

우선 Byte는 8개의 bit로 이뤄져 있다. (1Byte = 8bit)
bit 가 표현 가능한 상태의 수는 2^x (x는 bit의 수, x >= 1) 로 표현이 가능하다.
Byte 는 8개의 비트라 256개의 표현이 가능하다. (2^8 = 256)

MB, GB 도 있는데 byte를 설명한 이유는, 컴퓨터에서 사용되는 단위는 SI 접두어 + Byte로 표현하기 때문이다.
(Mega, Giga 다 SI 접두어다.)

2. 자료형의 음수, 양수 표현

2.1 자료형의 단위 

Java 자료형의 단위는 byte로 표현이 가능하다. (boolean은 Virtual Machine Dependent 이므로 제외한다.)

원시 자료형을 나타낸 표를 다시보자.

자료형 키워드 크기 기본값(전역변수 한정) 표현범위
논리형 boolean 미정
Virtual Machine Dependent
false true, false
문자형(유니코드) char 2byte \u0000 0 ~ 65,535
정수형 byte 1byte 0 -128 ~ 127
short 2byte 0 -32768 ~ 32767
int 4byte 0 -2147483648 ~
2147483647
long 8byte 0 -9223372036854775808 ~
9223372036854775807
실수형 float 4byte 0.0 -3.4E38 ~ +3.4E38
double 8byte 0.0 -1.7E308 ~ +1.7E308

2.3 자료형의 음수, 양수 표현

표를 살펴보면 위에 서술한 내용과 맞지않는 부분이 있다.
byte 자료형은 1byte로 이뤄져 있는데, 표현 범위는 왜 -127 ~ 128 인가?

1byte가 표현 가능한 상태의 수는 256개이다. 이 때 첫 비트는 + or - 의 상태를 나타내기 때문이다.
즉 Signed 자료형이기 때문이다. 아래 자료를 살펴보자.

0번 bit 1번 bit 2번 bit 3번 bit 4번 bit 5번 bit 6번 bit 7번 bit 결과
0 0 0 0 0 0 0 1 1
0 0 0 0 0 0 1 0 2
0 1 1 1 1 1 1 1 127

즉 0번 bit 가 0인 경우가 양수, 1인 경우가 음수를 표현하게 된다.

그럼 이제 다음 자료를 살펴보자.

0번 bit 1번 bit 2번 bit 3번 bit 4번 bit 5번 bit 6번 bit 7번 bit 결과
1 0 0 0 0 0 0 1 -1
1 0 0 0 0 0 1 0 -2
1 1 1 1 1 1 1 1 -127

이 자료는 틀린 자료이다. 0번 bit로 인해 -가 붙는것은 맞다. 하지만 음수의 bit는 양수와 반대로 표현된다.
이것을 이해하기 위해 보수의 개념을 알아야 한다. 

컴퓨터의 연산에 주로 사용되는 보수는 1의 보수(Ones' Complement), 2의 보수(Two's Complement) 이다.
보수는 보충해주는 수 라는 뜻으로, 컴퓨터에는 -의 개념이 없기 때문에 이런 방식을 사용한다.

1의 보수부터 살펴보자.

2.4 1의 보수 (Ones' Complement)

1의 보수는 영어로 "ones' complement"인데, 이를 직역하면 "1의 보수"가 된다(소유격을 나타내는 ' 기호가 s뒤에 있음에 유의). 즉, 1의 보수를 다르게 표현하자면 "여러 개의 1들로만 이루어진 수(111....)에 대한보수"라고 할 수 있다.
(출처 : 위키백과)

2.4.1 전자 회로 기초 논리 게이트

1의 보수를 설명하기 전 왜 1의 보수를 사용하여 연산하는지를 먼저 설명하고자, 기초 논리 게이트에 대해
서술하려 한다. 컴퓨터는 논리 게이트들의 덩어리와 같다. 기초 논리 게이트는 다음과 같다.

결과는 (X, Y) Result로 표현하겠다.

AND InputY (0) InputY (1)   OR InputY (0) InputY(1)   NOT  
InputX (0) (0, 0) 0 (0, 1) 0   InputX (0) (0, 0) 0 (0, 1) 1   InputX (0) (0) 1
InputX (1) (1, 0) 0 (1, 1) 1   InputX (1) (1, 0) 1 (1, 1) 0   InputX (1) (1) 0
  1. AND게이트  : 피 연산자가 같으면 1 그 외에는 모두 0을 반환한다.
  2. OR  게이트  : 피 연산자가 다르면 1 그 외에는 모두 0을 반환한다.
  3. NOT 게이트 : 피 연산자를 반전해 반환한다.

이런 기초 논리 게이트들을 조합하여 XOR, NAND, NOR를 만들 수 있다. 연산자 파트에서 다루도록 하겠다.

2.4.2 1의 보수 만들기

1의 보수를 만들때 크게 두가지의 방법이 있는데, 가장 간단한 반전시켜 얻는 방법을 알아보자.

말 그대로 모든 비트를 반전시켜주면 된다. 즉 모든 비트를 NOT게이트를 사용하여 처리해주면 된다.

15에 대한
1의보수
0번 bit 1번 bit 2번 bit 3번 bit 4번 bit 5번 bit 6번 bit 7번 bit
피연산자 0 0 0 0 1 1 1 1
결과 1 1 1 1 0 0 0 0

피연산자 : 15
결     과 : -15

이렇게 음수와 양수를 반전시킬 수 있다.

이렇게 1의보수를 만드는 방법과, 양수 음수의 반전을 알아봤다.

그럼 다시 돌아가서

0번 bit 1번 bit 2번 bit 3번 bit 4번 bit 5번 bit 6번 bit 7번 bit 결과
1 0 0 0 0 0 0 1 -1
1 0 0 0 0 0 1 0 -2
1 1 1 1 1 1 1 1 -127

의 결과가 틀렸다 얘기했는데, 바른값으로 고치면 다음과 같다.

0번 bit 1번 bit 2번 bit 3번 bit 4번 bit 5번 bit 6번 bit 7번 bit 결과
1 0 0 0 0 0 0 1 -127
1 0 0 0 0 0 1 0 -126
1 1 1 1 1 1 1 1 -1

그래도 이상한 결과가 보인다. 
1111 1111은 0000 0000을 1의 보수한 결과인데, 위의 내용으로는 1의 보수는 음수와 양수의 반전인데,
절대값이 바뀌어 버린다. 

마찬가지로 0111 1111 역시 1의 보수한 결과는 -0이 나오게 된다.
프로그래밍에서 -0, +0 즉 0이 두개라는 것은 엄청난 에러를 불러오게 된다. 그래서 우리는 음수 양수를 반전할 때
2의 보수를 사용해야한다

2의 보수는 1의 보수 한 결과에 +1 해주면 2의 보수이다.
그럼 byte 기준으로 2의 보수하는 과정을 알아보자.

  0번 bit 1번 bit 2번 bit 3번 bit 4번 bit 5번 bit 6번 bit 7번 bit
피연산자 1 0 0 0 0 0 0 0 0
결과 1 0 0 0 0 0 0 0 0
피연산자 2 0 0 0 0 1 1 1 1
결과 2 1 1 1 1 0 0 0 1

0에 1의 보수를 실행하면 1111 1111 이 나온다고 했다. 이제 여기에 1을 더하면 2의 보수라고 얘기를 했다.
그런데 1을 더하면, 0001 0000 0000 이 나오는게 아닌가 하고 생각할 수 있다.
이것은 carry의 개념인데, 자릿수를 초과하는, 즉 "0001" 0000 0000 부분은 carry가 되어 사라지게 된다.
그로 인해 0의 보수는 0이 된 것이고, 0은 양수에 속하게 되었다.
기존의 -0 인 1000 0000 은 -128을 표현하는 수가 되었다.

 

결과 및 마무리

따라서 양수의 범위는 '0 ~ 127'이 되었고, 음수의 범위는 '-1 ~ -128'이 되었다.

추가로 위에서는 signed 만을 다뤘는데, unsigned는 부호를 나타내는 0번 비트를
부호로 사용할지, 값으로 사용할지 선택한다. 즉 0 ~ 255의 값을 나타낼 수 있다.

반응형

관련글 더보기

GitHub 댓글

댓글 영역