본문 바로가기

Study/웹기초

overflow/underflow

1. 비트와 바이트

 

비트

컴퓨터는 모든 데이터를 0 또는 1만으로 표현합니다.

0 또는 1만 표현할 수 있는 하나의 메모리 조각을 비트(bit)라고 합니다.

바이트

1바이트는 8개의 비트로 구성돼 있습니다.

1비트마다 2가지 값을 표현할 수 있기 때문에 1바이트는 총 256(2^8) 개의 값을 표현할 수 있습니다.

 

 

LSB(Least Significant Bit) - 최하위 비트

일단 LSB의 위치는 가장 값이 작은 비트인 2^0에 위치하고 있는 것을 알 수 있습니다. 이 LSB의 값을 이용하여 해당 데이터 형에 들어있는 실제 숫자가 짝수인지 홀수인지 손쉽게 알아낼 수 있습니다.

MSB(Most Significant Bit) - 최상위 비트

MSB를 살펴보면 MSB 위치가 부호자리를 나타내고 있는 것을 알 수 있습니다. MSB가 1이면 음수, 0이면 양수 입니다. MSB의 값을 이용하여 양수인지 혹은 음수인지를 손쉽게 알아낼 수 있습니다.

 

 

 

이진수에서 음수를 표현하는 방법

1. 부호 절대값

첫번째 자리를 부호로 사용하고 나머지 자리를 숫자로 사용하는 방식 입니다.

 


0111 1111 ———> 127
0111 1110 ———> 126

0000 0010 ——> 2
0000 0001 ——> 1
0000 0000 ——> 0

 

1000 0000 ——> -0
1000 0001 ——> -1
1000 0010 ——> -2

1111 1110 ——> -126
1111 1111 ——> -127

 

8비트에서 -127 ~ 127 사이의 수를 나타낼 수 있고 -0이 존재합니다.

 

예시) -33을 이진수로 변환할 때 부호절대값 사용하기

  1. 10진수 33 을 2진수로 표현하면 0010 0001 입니다.
  2. MSB를 1로 바꿔줍니다 → 1010 0001

2. 1의 보수

보수는 보충을 해주는 수를 의미합니다.
→ 1에 대한 10의 보수는 9, 4에 대한 15의 보수는 11의 개념입니다. 2에 대한 1의 보수는 1입니다.
→ K진법의 어떤 수 N이 있을때, N의 자릿 수를 하나 더 증가시키기 위해서 필요한 최소의 값

 

음수를 표현할 때 1의 보수를 이용하는 방식입니다.

1에 대한 1의 보수는 0이고, 0에 대한 1의 보수는 1 입니다.
즉 이진수에서 1의 보수는 모든 비트를 반전시키는 not 비트연산을 한 수 입니다. (1→ 0, 0→1)

 


0111 1111 ———> 127
0111 1110 ———> 126

0000 0011 ———> 3
0000 0010 ———> 2
0000 0001 ———> 1
0000 0000 ———> 0

 


1111 1111 ———> -0
1111 1110 ———> -1
1111 1101 ———> -2

1000 0001 ———> -126
1000 0000 ———> -127

 

예시) 10진수 -33을 이진수로 변환할 때 1의 보수 사용하기

  1. 33 을 2진수로 표현하면 0010 0001 입니다.
  2. 모든 비트를 반전시키면 1101 1110 입니다.

장점

  1. 2의 보수에 비해 음수를 만들기 간편합니다.

단점

  1. 부호가 있는 0이 2개가 생성이 됩니다. +0 = 0000 0000 -0 = 1111 1111
  2. +,- 등의 연산이 복잡합니다.

 

3. 2의 보수

마지막으로 이진수의 2의 보수를 음수로 나타내는 방법입니다.
컴퓨터에서 음수를 나타낼 때에는 2의 보수를 사용합니다.
이진수의 2의 보수를 구하려면 1의 보수를 구한 후 1을 더해줍니다. (모든 비트를 반전시킨 후 +1을 해줍니다)

0111 1111 ———> 127

0111 1110 ———> 126

0000 0011 ———> 3

0000 0010 ———> 2

0000 0001 ———> 1

0000 0000 ———> 0

 

1111 1111 ———> -1

1111 1110 ———> -2

1000 0001 ———> -127

1000 0000 ———> -128

 

8비트에서 -128 ~ 127 사이의 수를 나타낼 수 있습니다.

 

예시) 10진수 -33을 2의 보수를 사용해서 이진수의 음수로 표현

  1. 33 을 2진수로 표현하면 0010 0001 입니다.
  2. 모든 비트를 반전시켜줍니다. → 1101 1110
  3. 1을 더합니다 → 1101 1111

음수를 다시 양수로 바꾸기 위해서는 먼저 1을 빼고 비트 반전을 시켜줍니다.

 

장점

  1. 1의 보수에 비해 연산이 간단합니다.
  2. 0이 한개 뿐이므로 혼란이 생기지 않습니다.

단점

  1. 1의 보수에 비해서 음수만들기가 복잡합니다.

 

 

2. 정적 타입 언어 vs 동적 타입 언어

 

자료형이란?

변수의 종류를 의미합니다.


💡 Java 자료형
기본형(Primitive Type) : byte, short, int, long, float, double, char, boolean
참조형(Reference Type) : class, interface, array


💡 JavaScript 자료형
기본형(Primitive Type) : symbol, undefined, null, string, number, boolean
참조형(Reference Type) : object (기본형이 아닌 모든자료형)

 

 

자료형 존재이유?

  • 메모리의 낭비를 최소화하기 위해 데이터 타입별로 할당할 메모리 영역을 바이트로 나누어 정해놓았습니다.
  • 할당된 메모리의 범위보다 큰 수나 적은 수를 입력하면 오류가 나거나 잘못된 값이 저장되는 경우가 생깁니다. 이를 대응하기 위해서는 직접 상위 크기의 타입으로 형변환을 해야 합니다.
  • 메모리가 부족했던 시절에는 이러한 선택이 불가피했다고 합니다.

 

 

정적 타입 언어

 

정적 타입 언어는 컴파일 시 변수의 타입(자료형)이 결정되는 언어를 말합니다. (Java, C, C++, C#, ...)

컴파일 시에 자료형에 맞지 않는 값이 들어있으면 에러가 발생하기 때문에, 개발자가 변수에 직접 타입을 명시해줘야 합니다.

 

💡 컴파일이란? 프로그래머가 작성한 소스코드를 바이너리 파일(이진파일 = 컴퓨터 언어)로 변환하는 과정.

String name ="tuna"
int num = 123


장점

  1. 타입 에러로 인한 문제점을 초기에 발견할 수 있어 타입의 안정성이 높음
  2. 컴파일 시에 미리 타입을 결정하기 때문에 실행속도가 빠름

단점

  1. 매번 코드 작성 시 변수형을 결정해줘야 하는 번거로움이 있음

 

동적 타입 언어

 

동적 타입 언어는 컴파일 시 자료형을 정하는 것이 아니라 런타임 시 결정됩니다. (Python, JS, Ruby, PHP, ...)

다음과 같이 타입 없이 변수만 선언하여 값을 지정할 수 있습니다.

let num = 123
num = "일이삼"

예시와 같이 타입 선언이 없었지만,  num이 123 이란 숫자로 선언이 됩니다. 두 번째 줄에 num을 string으로 다시 선언하더라도 타입 에러 없이 컴파일됩니다.

  • 동적 타입 언어는 타입을 따로 지정하지 않아도 할당된 값을 통해 동적으로 타입을 지정합니다.
  • 메모리가 과거보다 월등히 커진 상황에서 등장했기 때문에 메모리 공간을 좀 더 넉넉하게 할당하는 방식을 선택했기 때문입니다.
  • 숫자의 경우 따로 구분하지 않고 64비트(8바이트)를 확보하기 때문에 형변환의 걱정을 덜어줬습니다.

장점

  1. 런타임까지 타입에 대한 결정을 끌고 갈 수 있기 때문에 유연성이 높음
  2. 컴파일 시 타입을 명시해주지 않아도 되기 때문에 빠르게 코드를 작성할 수 있음

단점

  1. 실행 도중에 변수에 예상치 못한 타입이 들어와 타입에러가 발생할 수 있음. -> TypeScript를 사용하는 이유.

 

 

 

3. overflow / underflow

  • Overflow (오버플로우) : 메모리의 표현 범위에서 벗어난 수의 값을 저장하는 경우
  • Underflow (언더플로우) : 메모리가 표현할 수 있는 수보다 적은 수의 값을 저장하는 경우

위에서 설명했듯이 정적 타입 언어는 컴파일할 때 변수의 타입이 결정되기 때문에, 변수를 선언할 때 자료형을 별도로 지정해주어야 합니다.
이처럼 정적타입언어에서의 자료형은 데이터를 표현할 수 있는 범위가 정해져 있기 때문에,
변수 범위 밖으로 넘어가게 되면 예상치 못한 값들이 반환되게 되는데 이 현상이 바로 OverflowUnderflow 입니다.

 

2진수로 표현하면 오버플로우가 왜 발생했는지 쉽게 이해할 수 있습니다.

 

01111111 [127] + 1 = 10000000 [-128]이 되고,

10000000[-128] - 1 = 01111111 [127]이 된다.

 

부호를 결정하는 맨 왼쪽 비트가 바뀌게 되니 이런 결과가 생기는 것입니다.
자료형의 최댓값에서 1을 더하면 최솟값이 되고, 최솟값에서 1을 빼면 최댓값이 됩니다.

 

 

ex) 정수의 오버플로우(자바의 정석)

 

 

 

💡 오버플로우가 일어난 실제 예시

 

 

 

💡 255, 65535 제한이 있는 이유

IP 주소를 보면 212.122.102.20 식으로 표현되는데, 각 자리는 1바이트로 표현되기 때문에

IP 주소에 256 이상의 숫자가 나오지는 않습니다.

옛날 게임을 보면 수의 최대치가 65535 이상으로 넘어가지 않는 경우가 있습니다.

 

대부분의 컴퓨터 시스템에서, 8 비트 길이를 가지는 정보의 기본 단위로 바이트(byte)를 사용합니다.

각 비트로 표현 가능한 경우의 수는 2가지이며, 따라서 1바이트는 2^8까지 표현 가능하죠. 즉, 2^8 = 256 이라는 것이죠.

그리고 때로는 더 큰 데이터를 다루기 위해서 2바이트를 사용하는 경우 2^16이 한계 수치로 65536이 됩니다.
( 일반적으로 표현하는 수가 0부터 시작하기 때문에 255, 65535 가 최대값으로 사용됩니다. )

'Study > 웹기초' 카테고리의 다른 글

WS vs WAS  (0) 2023.05.18
SSR vs CSR  (0) 2023.05.17
macOS 터미널에서 내 IP 주소 확인하기  (0) 2022.11.11
응집도 vs 결합도  (0) 2022.10.05
객체 지향의 3가지 특징 - 캡슐화, 상속, 다형성  (1) 2022.10.05