파이썬

1.1 + 0.1 == 1.2가 "False"인 이유를 아는지~?

supersumin 2024. 7. 28. 19:19

위와 같은 결과가 나오는 이유에 대해서 알아보자

 

1. 컴퓨터는 숫자를 어디에 저장하는가?

: 주로 메모리(RAM)와 저장장치(HDD, SSD)에 저장된다. 또한 CPU 내의 레지스터도 숫자를 일시적으로 저장하는 공간으로 사용된다.

1.1. RAM(Random Access Memory)

- 기능: 프로그래밍이 실행 중일 때 데이터를 임시로 저장하는 공간이다.

- 특징: 빠른 속도로 데이터에 접근할 수 있지만, 휘발성 메모리이므로 전원이 꺼지면 데이터가 사라진다.

- 용도: 현재 실행 중인 프로그래밍의 변수, 실행 코드, 데이터 등을 저장한다.

 

1.2. 저장장치(Storage)

- 종류: HDD(hard Disk Drive), SSD(Solide State Drive)

- 기능: 데이터를 영구적으로 저장하는 공간이다.

- 특징: 비휘발성 메모리이므로 전원이 꺼져도 데이터가 유지된다.

 

1.3. CPU Register

- 기능: CPU가 연산을 수행하는 동안 데이터를 일시적으로 저장하는 초고속 메모리이다.

- 특징: 매우 빠른 속도로 데이터에 접근할 수 있지만 용량이 매우 작다.

- 용도: 연산 중인 데이터, 주소, 명령어 등을 저장한다.

 

1.4. 캐시(Cache) 메모리

- 기능: CPU와 메모리 사이의 속도 차이를 줄이기 위해 사용되는 고속메모리이다.

- 특징: 휘발성 메모리이며, CPU 내부 또는 가까이에 위치한다.

- 용도: 자주 사용되는 데이터와 명령어를 임시로 저장하여 CPU가 빠르게 접근할 수 있도록 한다.

 

프로그래밍 하는 도중 a라는 변수에 5라는 값을 넣었다고 가정

-> RAM에 5라는 값이 bit라는 칸에 0과 1로 표현되면서 저장

8개의 칸인 bit에 5를 표현해본 모습이다. bit의 수가 8개 있으므로 맨 앞의 bit는 부호를 나타내기 위해 제외하면 -128~127까지 표현할 수 있다.

 

참고로 16개의 칸으로는 

-32,768에서 32,767까지 표현할 수 있다.

 

32개의 칸은 

-2,147,483,648에서 2,147,483,647까지의 값을 표현할 수 있다.

 

 

2. 그렇다면 숫자를 어떻게 정리하는가?

컴퓨터는 정수형과 실수형을 나누어서 변수를 사용하게 된다. 그 이유는 저장되고 처리되는 방식의 차이가 존재하기 때문이다.

- 정수형: 0, 양수, 음수와 같은 정확한 값을 가지기 때문에 표현에 오차가 발생하지 않는다.

- 실수형: 유리수, 무리수, 유한 소수, 무한 소수를 모두 표현하기 위해 실수형 데이터는 부동소수점(floating-point) 표현을 사용하여 근사값으로 저장된다. 이 과정에서 근사값으로 인해 오차가 발생할 수 있다. 순환 소수를 일정 부분에서 반올림하여 나머지 값은 버리기 때문이다.

-> "정확한 계산을 위한 프로그램을 짠다면 실수형이 아닌 정수형 변수를 사용"

 

* 부동소수점과 고정소수점의 차이 *

- 고정 소수점 방식

: 실수를 정수부와 소수부로 나누어 표현한다.

ex) 123.456을 표현할 때, 123은 정수부, 456은 소수부로 나누어 저장

이 방식의 장점은 계산의 정확도가 높다. 고정된 비트 수로 정수부와 소수부를 표현하기 때문에, 계산 과정에서 발생할 수 있는 오차를 최소화할 수 있기 때문입니다.

이 방식의 단점은 표현할 수 있는 수의 범위가 제한적이다. 정수부와 소수부의 비트 수가 고정되어 있기 때문에 정수의 표현이 유동적이지 않아 값이 한정적이고, 가수의 표현이 유동적이지 않아 정확성이 떨어진다.

 

- 부동 소수점 방식

: 실수를 가수부와 지수부로 나누어 표현합니다. 이 방식은 실수를 '가수 × 2^지수'의 형태로 저장하며, 이를 통해 넓은 범위의 실수를 표현할 수 있다.

부동 소수점 방식의 장점은 표현할 수 있는 수의 범위가 매우 넓다. 가수부와 지수부를 조절함으로써 매우 크거나 매우 작은 수도 효율적으로 표현한다.

이 방식의 단점은 계산 과정에서 오차가 발생한다. 실수를 이진법으로 변환하는 과정에서 무한 소수가 발생할 수 있으며, 이로 인해 정밀도가 상대적으로 낮아진다.

부동 소수점 방식은 컴퓨터 그래픽, 게임 개발, 대규모 과학적 계산 등에서 널리 사용된다.

 

 

* 실수형 표현 방식(ex double precision) *

: IEEE 754 표준을 사용하여 실수형 데이터를 저장한다.

float(단정도 부동소수점): 32bits

- 상위 1비트: 부호 비트

- 8비트: 지수

- 23비트: 가수 

double(배정도 부동소수점): 64bits

- 상위 1비트: 부호 비트

- 11비트: 지수

- 52비트: 가수 

-> float는 가수가 23비트이며 더 정확한 소수를 표현하고 싶다면 double을 사용하게 된다. 하지만 float에 비해 메모리는 2배 더 차지하게 된다.

 

 

0.125(10) = 0.001(2) 

0.1(10)= 0.0001100110011001100110011001100110011001100110011001100…(2)

 

 

3. 그렇다면 왜 오류가 나며 왜 값이 더 큰가?

0.1의 이진법 표시와 같이 순환소수가 발생한다면 제한된 bit 수에서 표현하기 위해 float는 가수의 24번째 비트에서 반올림, double은 가수의 53번째 비트에서 반올림하기 때문에 반올림 하는 순간 값이 0.1보다 커지기 때문에 오차가 발생한다.

- 1.1과 0.1은 각각 memory에 저장될 때 1.1의 이진법이 특정 값에서 반올림된 값, 0.1의 이진법이 특정 값에서 반올림된 값이 저장되게 된다. 그러므로 1.2의 이진법이 특정 값에서 반올림된 값보다 클 수밖에 없다.

- "1.1+1"에서 1.1은 1.1의 특정한 값에서 반올림된 값과 1이라는 정확한 숫자의 합이다. "2.1"또한 특정한 값에서 반올림된 값이지만 첫 번째 식과 결과가 다른 이유는 첫 번째 식은 좌변이 반올림이 진행된 값이 두 개이고 우변은 한 개이다. 세 번째 식은 양변에 반올림이 진행된 값은 각각 하나이며, 0.1은 두 값 똑같은 값에서 반올림이 진행된 똑같은 값이기 때문에 "True"가 나오게 된다.

 

 

 

@ 요약

1. RAM에는 숫자를 특정 bit 수에 맞춰서 저장한다.

2. 정수형은 값을 정확히 저장할 수 있지만 실수형은 이진법으로 표현했을 때 순환소수가 나타나는 경우가 발생하므로 근사치 즉, 특정한 값에서 반올림이 진행되어 값이 정확하지 않다.

3. 정확한 계산을 위한 프로그래밍은 실수형보다 정수형으로 계산하는 것이 낫다.

4. float보다 double이 가수를 표현하는 bit 수가 많기 때문에 더 정확하지만 64개의 bit 즉, 8bytes를 차지하기 때문에 float모다 메모리를 두 배 차지한다.