🔥 숫자 상수

252자
3분

숫자 상수는 높은 정밀도의 을 나타냅니다. 상수를 선언할 때 타입을 지정하지 않으면 컨텍스트에 맞는 타입이 자동으로 부여되죠. 아래 코드에서 Big이라는 상수를 만들어 봅시다. 이 상수는 1을 왼쪽으로 100번 시프트한 값, 즉 2의 100제곱을 나타낼 거예요. 엄청나게 큰 수겠죠?

go
const (
    // 1을 왼쪽으로 100번 시프트하여 엄청나게 큰 수를 만듭니다.
    // 바이너리로 표현하면 1 뒤에 0이 100개 붙은 형태입니다.
    Big = 1 << 100
    // 다시 오른쪽으로 99번 시프트하면 1<<1, 즉 2가 됩니다.
    Small = Big >> 99
)
 
go
const (
    // 1을 왼쪽으로 100번 시프트하여 엄청나게 큰 수를 만듭니다.
    // 바이너리로 표현하면 1 뒤에 0이 100개 붙은 형태입니다.
    Big = 1 << 100
    // 다시 오른쪽으로 99번 시프트하면 1<<1, 즉 2가 됩니다.
    Small = Big >> 99
)
 

Big은 1을 왼쪽으로 100번 시프트한 값이에요. 바이너리로 표현하면 1 뒤에 0이 100개 붙은 형태가 됩니다. 그리고 SmallBig을 다시 오른쪽으로 99번 시프트한 값이에요. 따라서 Small의 값은 2가 됩니다.

이제 needIntneedFloat 함수를 정의해 볼까요? needInt 함수는 인자로 받은 int 타입 변수에 10을 곱하고 1을 더해서 반환합니다. needFloat 함수는 인자로 받은 float64 타입 변수에 0.1을 곱해서 반환하죠.

go
func needInt(x int) int { return x*10 + 1 }
func needFloat(x float64) float64 {
    return x * 0.1
}
 
go
func needInt(x int) int { return x*10 + 1 }
func needFloat(x float64) float64 {
    return x * 0.1
}
 

자, 이제 main 함수에서 needIntneedFloat 함수를 호출해 봅시다. Small을 인자로 넘기면 어떤 결과가 나올까요?

go
func main() {
    fmt.Println(needInt(Small))
    fmt.Println(needFloat(Small))
    fmt.Println(needFloat(Big))
}
 
go
func main() {
    fmt.Println(needInt(Small))
    fmt.Println(needFloat(Small))
    fmt.Println(needFloat(Big))
}
 

needInt(Small)은 21을 출력할 거예요. needFloat(Small)은 0.2를 출력하겠죠. 그런데 needFloat(Big)은 어떤 결과가 나올까요? 실행해 보면 오버플로우가 발생한다는 걸 알 수 있어요.

text
21
0.2
+Inf
text
21
0.2
+Inf

Big은 너무 큰 숫자라서 float64 타입으로 표현할 수 없습니다. 따라서 오버플로우가 발생하고 +Inf(양의 무한대)가 출력되는 거죠.

참고로 int 타입은 최대 64비트 정수까지 저장할 수 있어요. 하지만 플랫폼에 따라서는 더 작은 범위만 표현할 수도 있습니다. 따라서 아주 큰 숫자를 다룰 때는 주의해야 해요.

YouTube 영상

채널 보기
Product와 Coproduct가 Bifunctor인 이유 | 프로그래머를 위한 카테고리 이론
List 펑터 - 왜 map은 for 루프보다 강력한가? | 프로그래머를 위한 카테고리 이론
커스텀 예외 필터 만들기 | NestJS 가이드
NestJS 파이프가 뭔가요? 컨트롤러를 보호하는 방법 | NestJS 가이드
바이펑터란? | 프로그래머를 위한 카테고리 이론
NestJS 표준 예외 처리와 HttpException | NestJS 가이드
리더 펑터 - 함수도 펑터다! | 프로그래머를 위한 카테고리 이론
펑터 합성 | 프로그래머를 위한 카테고리 이론