Chapter 4. 변수

조성권·2021년 8월 5일
0

오늘은 정수형실수형에 대해 배워보고자 한다.
Golang에서 정수실수는 어떻게 표현되고 연산의 결과는 어떻게 처리되는지 공부해보겠다.

1. 정수형 변수

1-1 정수 Type

정수형 Type에는 다양한 종류가 있다.
하지만 사실 상, 모든 Type에 대해 사용하진 않을 것으로 판단되기에 몇가지만 추려서 적어보도록 하겠다.

unit16: 부호 없는 16비트 정수형 (0 ~ 65,535)
uint32: 부호 없는 32비트 정수형 (0 ~ 4,294,967,295)
int32: 부호 있는 32비트 정수형 (-2,147,483,648 ~ 2,147,483,647)
int64: 부호 있는 64비트 정수형 (-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807)
int: 32비트 시스템에서는 int32, 64비트 시스템에서는 int64

이외에도 더 많은 Type이 존재하지만 따로 기재하진 않겠다.
대부분의 경우, 가장 많이 쓰게 되는 Type은 int가 될 것이므로 이 Type의 값의 범위가 상황에 따라 어떻게 달라지는지만 이해하는 정도면 충분할 것으로 판단된다.

1-2 정수 Type 예제

간단하게 각 Type 범위에 따라 어떤 문제가 발생하는지 예제를 통해 짚어보겠다.

	var num3 uint16 = 10
	var num4 uint32 = 80000

	fmt.Println(uint16(num4))        // 14464
	fmt.Println(num3 + uint16(num4)) // 14474

최초 다음과 같이 변수를 정의했을 때, 문제가 되는 부분은 없다.
각 Type별로 정해진 범위 내, 정수로 초기화했기 때문이다.
하지만 '더 큰 범위 Type'을 '더 작은 범위 Type'으로 바꾸는 것은 주의해야 한다.

uint16(num4)를 진행하며 80,000이라는 값이 14464로 임의 수정되었다.
Why? uint16의 최대 값은 65,535이기 때문이다.

그렇기 때문에 최종적으로 num3와 합친 값도 의미없는 값이 출력되게 되는 것이다.
그러므로 Type을 선언할 때, 반드시 자신이 대입하고자 하는 값이 어떤 Type 범위에 속하는지 확인하고 사용해야 한다.

2. 실수형 변수

2-1 실수 Type

실수형 Type은 크게 2개의 Type으로 나누어진다고 볼 수 있다.

  • float32: IEEE-754 32비트 부동소수점, 7자리 정밀도
  • float64: IEEE-754 64비트 부동소수점, 12자리 정밀도

정밀도의 차이가 존재하며 float64가 더 근접한 값을 가져온다고 볼 수 있다.

2-2 실수의 연산

실수의 연산에선 주의할 점이 있다. 바로 오차범위이다.
컴퓨터는 2진수를 사용하고 2진수로는 실수를 정확하게 표현할 수 없다. 무한한 실수의 범위에 비해 유한한 Bit를 가지고 표현하기 때문이다.
이러한 문제를 바로 부동소수점 반올림 오차(Rounding error)라고 한다.

아래 예시를 통해 이야기를 이어 나가보겠다.

	var data float64 = 10.0

	for i := 0; i < 10; i++ {
		data -= 0.1
	}

	fmt.Println(data) // 9.000000000000004

	const epsilon = 1e-14

	if math.Abs(data-9.0) <= epsilon {
		fmt.Println("It's smaller than epsilon")
	} else {
		fmt.Println("It's bigger than epsilon")
	}

위 예제는 float64를 통해 12자리 정밀도를 보장한다.
우리가 생각하기에 10.0에서 1.0(=for문을 통해 0.1을 10번 뺀 값)을 뺀다면 9.0이 나와야 한다.

하지만 실제 이 값을 출력하면 9.000000000000004 즉, 0.000000000000004의 오차가 발생한 것이다.
만약, if data == 0.9 {~}와 같은 조건문이 있었다면 이 프로그램은 정확성을 보장할 수 없었을 것이다.

그러므로 절대 실수의 연산에 대한 결과 값을 추가적인 가공없이 바로 사용해선 안된다.

이러한 상대 오차는 항상 머신 입실론 이하이다.

머신 입실론: 부동 소수점 연산에서 1보다 큰 최소의 수와 1과의 차
Go에선 머신 입실론1e-14로 간주

다음 조건문은 그 차이의 크기를 증명하는 구문이다. 실제로 구문을 실행해보면 "It's smaller than epsilon"이라는 결과가 출력되는 것을 확인할 수 있다.

결과적으로 정리하면 실수 연산은 오차범위가 존재하며 그 범위는 머신 입실론 이하이다.

3. 정수형과 실수형의 연산

이제 정수형과 실수형 Type을 혼합하여 연산하는 과정을 확인해보겠다.

	var num1 int = 10
	var num2 float32 = 2.2

	fmt.Println(num1 + num2)          // Compile Error
	fmt.Println(num1 + int(num2))     // 10 + 2 = 12
	fmt.Println(float32(num1) + num2) // 10.0 + 2.2 = 12.2

위 예제에서 가장 중요한 경우는 num1 + num2 Case이다.
사실, Casting을 통해 '정수형의 실수형 변환'하고
'실수형의 정수형 변환
작업은 프로그래밍을 해본 사람이라면 대부분 이해할 것이다.

하지만 Golang에서 '정수형과 실수형'을 그냥 연산할 경우, Compile Error가 난다는 것은 반드시 짚고 넘어가야한다.

4. 마무리

오늘은 정수형/실수형 Type에 대해 간단히 알아보았다.
Type의 종류는 너무나도 많지만 실제 사용할 법한 Type에 대해서만 간략히 노트해보았다.
오늘 정리한 내용을 바탕으로 숫자에 대한 연산은 절대 틀리지 않겠다!

전체소스 git 링크
https://github.com/cho876/Go/blob/main/Prac04/Prac04.go

profile
천천히, 완벽히 배워나가고자 하는 웹 서비스 엔지니어

0개의 댓글