🔥 숫자 상수

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 영상

채널 보기
Trie 자료구조 파이썬 구현: Search와 Starts With 연산 | Trie 자료구조 이야기
Trie(트라이) 자료구조 원리와 파이썬 클래스 설계 및 구현 | Trie 자료구조 이야기
마지막편, 트라이 노드를 50% 이상 줄이는 방법? 압축 트라이 성능 분석 | Trie 자료구조 이야기
13편, 인덱스가 많으면 왜 느려질까? 쓰기 증폭과 인덱스 튜닝의 이해
숫자 하나가 AI 모델의 운명을 바꾼다? | 선형대수학
벡터의 정의와 덧셈 연산 | 선형대수학
AI를 위한 선형대수학 - 소개 | 선형대수학
트라이(Trie)에서 단어를 삭제하는 방법 | Trie 자료구조 이야기