8. IEEE 754 규약을 따르는 실수, 오차 범위에 주의
안녕하세요. 언제나 휴일, 언휴예요. 이번에는 Go 언어에서 실수를 표현할 때 사용하는 float32(32비트)와 float64(64비트)를 소개할게요.
0.1과 0.2 사이에는 몇 개의 실수가 있을까요?
여러분이 아시는 것처럼 무한 개의 실수가 존재하죠. 컴퓨터에서는 메모리에 데이터를 표현하여 모든 실수를 유한한 메모리에 표현할 수는 없어요. 실제로 컴퓨터에 실수 표현은 오차 범위를 갖고 있어요.
Go언어에서는 IEEE 754 규약에 따라 실수를 표현하고 있어요. IEEE 754 규약에서는 실수를 부호부, 지수부, 가수부로 나누어 일정 범위의 오차 범위를 갖는 실수를 표현하는 것을 약속하고 있어요.
Go 언어에서는 IEEE 754 규약에서의 오차(10의 -14승)를 갖습니다. 다음은 float32 의 메모리 구조예요.
[그림 1] 32비트 실수의 메모리 구조
먼저 실수를 표현하는 방법을 알아보기로 해요. 새로운 프로젝트를 생성한 후에 표현해 보아요.
[그림 2] LiteIDE에서 새로운 프로젝트 생성 및 소스 파일 추가
실수를 표현할 때는 고정 소수점 표현 혹은 부동 소수점으로 표현할 수 있어요.
- 고정 소수점 표현
var f1 float32 = 0.1 //고정 소수점 표현
var f2 float32 = .1 //고정 소수점 표현
고정 소수점 표현은 일반적으로 실수를 표현하는 것처럼 0.1 처럼 표현할 수 있으며 만약 정수부가 없을 때는 .1 처럼 표현할 수도 있어요.
- 부동 소수점 표현
var f3 float32 = 1e-1 //부동 소수점 표현
[그림 3] 실수 표현 예제 실행 화면
그런데 실수를 사용할 때는 오차 범위가 있다는 것을 주의해야 합니다. 예를 들어 0.1을 10번 더한다고 정확한 1.0이 나오지 않아요. 이를 확인하기 위해 새로운 프로젝트를 생성하여 확인해 보아요.
[그림 4] LiteIDE에서 새로운 프로젝트 생성 및 소스 파일 추가
실수 f1을 선언하면서 0.0으로 초기화한 후에 0.1씩 더하고 출력해 보세요. 예상하는 값은 0.1, 0.2, 0.3, 0.4, ... 이지만 실제 확인해 보면 차이가 있다는 것을 알 수 있어요. 이는 컴퓨터에서 실수 표현은 오차 범위를 갖기 때문입니다.
var f1 = 0.0
f1 += 0.1
fmt.Println(f1)
f1 += 0.1
fmt.Println(f1)
f1 += 0.1
fmt.Println(f1)
f1 += 0.1
fmt.Println(f1)
...
Go 언어의 실수는 IEEE 754 규약을 따르며 오차 범위는 10의 -14승이예요. 따라서 실수 값을 갖는 변수와 비교하고자 하는 값을 뺀 후에 차이가 10의 -14승 이내에 있다면 오차 범위내에서 같은 값으로 취급할 수 있어요.
fmt.Println(f1 == 1.0) //오차 범위를 갖고 있으므로 버그일 수 있음
fmt.Println((f1 - 1.0) <= errbound)//오차 범위내에 같은 값인지 비교
[그림 5] 오차 범위를 갖는 실수 예제 실행 화면
관련 게시글
[구글 Go 하자] 5. 강력한 타입 언어, Go 언어 변수 선언 맛보기
[구글 Go 하자] 6. 표현 범위에 따라 원하는 정수 형식 사용
[구글 Go 하자] 7. byte와 rune 으로 바이너리 데이터 및 코드 표현
[구글 Go 하자] 9. Go 언어에서는 복소수를 표현하는 형식을 제공해요.
[구글 Go 하자] 10. math 패키지에서 제한값을 제공해요.
[구글 Go 하자] 11. 참과 거짓은 bool, 문자열은 string
'언어 자료구조 알고리즘 > 구글 Go' 카테고리의 다른 글
[구글 Go 하자] 13. iota를 사용하여 규칙적인 상수 열거하기 (0) | 2016.05.28 |
---|---|
[구글 Go 하자] 12. const 키워드로 상수 정의 (0) | 2016.05.28 |
[구글 Go 하자] 11. 참과 거짓은 bool, 문자열은 string (0) | 2016.05.28 |
[구글 Go 하자] 10. math 패키지에서 제한값을 제공해요. (0) | 2016.05.28 |
[구글 Go 하자] 9. Go 언어에서는 복소수를 표현하는 형식을 제공해요. (0) | 2016.05.28 |
[구글 Go 하자] 7. byte와 rune 으로 바이너리 데이터 및 코드 표현 (0) | 2016.05.27 |
[구글 Go 하자] 6. 표현 범위에 따라 원하는 정수 형식 사용 (0) | 2016.05.26 |
[구글 Go 하자] 5. 강력한 타입 언어, Go 언어 변수 선언 맛보기 (0) | 2016.05.26 |
[구글 Go 하자] 4. 깃허브 가입하고 LiteIDE 다운로드 및 테스트하기 (0) | 2016.05.25 |
[구글 Go 하자] 3. 윈도우즈에 Go SDK 설치 및 환경 설정하기 (0) | 2016.05.25 |