정수와 부동소수점 수

정수와 부동소수점 수

Julia 코드를 처음 쓰다 보면 마주치는 가장 기본적인 데이터가 정수와 부동소수점 수예요. 1은 정수 리터럴이고 1.0은 부동소수점 리터럴이죠. 이 값들은 메모리에 저장될 때 각각 정수형과 부동소수점형의 원시 타입(primitives)이 돼요. 이 글에서는 Julia가 제공하는 원시 숫자 타입의 종류, 리터럴이 타입을 결정하는 규칙, 오버플로우 동작, 임의 정밀도 산술까지 차근차근 살펴볼게요.

출처: Integers and Floating-Point Numbers — The Julia Language

본문

정수와 부동소수점 값은 산술과 계산의 기본 구성 요소예요. 이런 값을 내장된 형태로 표현한 것을 **원시 숫자 타입(numeric primitives)**이라 하고, 코드에 '즉시 값'으로 적은 정수·부동소수점 표현을 **숫자 리터럴(numeric literals)**이라고 불러요. 예를 들어 1은 정수 리터럴, 1.0은 부동소수점 리터럴이고, 이들이 객체로서 메모리에 저장된 이진 표현이 원시 숫자 타입이에요.

Julia는 넓은 범위의 원시 숫자 타입을 제공하고, 그 위에 산술 연산자와 비트 연산자, 표준 수학 함수를 빠짐없이 정의해요. 이들은 현대 컴퓨터가 기본적으로 지원하는 숫자 타입과 연산을 그대로 매핑해서, Julia가 하드웨어의 계산 자원을 충분히 활용할 수 있게 해줘요. 추가로 Julia는 임의 정밀도 산술을 소프트웨어로 지원해요. 하드웨어의 원시 표현으로는 제대로 담을 수 없는 큰 값의 연산도 처리해주지만, 상대적으로 성능은 느려져요.

다음은 Julia의 원시 숫자 타입 목록이에요.

  • 정수 타입:
타입 부호 비트 수 최솟값 최댓값
Int8 8 -2^7 2^7 - 1
UInt8 8 0 2^8 - 1
Int16 16 -2^15 2^15 - 1
UInt16 16 0 2^16 - 1
Int32 32 -2^31 2^31 - 1
UInt32 32 0 2^32 - 1
Int64 64 -2^63 2^63 - 1
UInt64 64 0 2^64 - 1
Int128 128 -2^127 2^127 - 1
UInt128 128 0 2^128 - 1
Bool 해당 없음 8 false (0) true (1)
  • 부동소수점 타입:
타입 정밀도 비트 수
Float16 half 16
Float32 single 32
Float64 double 64

이 원시 숫자 타입 위에는 복소수와 유리수 지원도 완전히 구축돼 있어요. 그리고 유연하고 사용자가 확장할 수 있는 타입 승격 시스템 덕분에, 모든 숫자 타입은 명시적인 캐스팅 없이도 자연스럽게 함께 동작해요.

정수

정수 리터럴은 일반적인 방식으로 표현돼요.

julia> 1
1

julia> 1234
1234

정수 리터럴의 기본 타입은 대상 시스템이 32비트 아키텍처인지 64비트 아키텍처인지에 따라 달라져요.

# 32비트 시스템:
julia> typeof(1)
Int32

# 64비트 시스템:
julia> typeof(1)
Int64

Julia의 내부 변수 Sys.WORD_SIZE를 보면 대상 시스템이 32비트인지 64비트인지 알 수 있어요.

# 32비트 시스템:
julia> Sys.WORD_SIZE
32

# 64비트 시스템:
julia> Sys.WORD_SIZE
64

Julia는 또한 IntUInt 타입을 정의하는데, 이들은 각각 시스템의 부호 있는/부호 없는 네이티브 정수 타입의 별칭이에요.

# 32비트 시스템:
julia> Int
Int32
julia> UInt
UInt32

# 64비트 시스템:
julia> Int
Int64
julia> UInt
UInt64

32비트로는 표현할 수 없지만 64비트로는 표현 가능한 더 큰 정수 리터럴은, 시스템 타입과 무관하게 항상 64비트 정수를 만들어요.

# 32비트든 64비트든:
julia> typeof(3000000000)
Int64

부호 없는 정수는 0x 접두사와 16진수(밑 16) 숫자 0-9a-f로 입력·출력돼요 (대문자 A-F도 입력에 사용 가능). 부호 없는 값의 크기는 사용된 16진수 자릿수로 결정돼요.

julia> x = 0x1
0x01

julia> typeof(x)
UInt8

julia> x = 0x123
0x0123

julia> typeof(x)
UInt16

julia> x = 0x1234567
0x01234567

julia> typeof(x)
UInt32

julia> x = 0x123456789abcdef
0x0123456789abcdef

julia> typeof(x)
UInt64

julia> x = 0x11112222333344445555666677778888
0x11112222333344445555666677778888

julia> typeof(x)
UInt128

이 동작은 이런 관찰에 기반해요. 정수 값으로 부호 없는 16진수 리터럴을 쓸 때, 대개 단순한 정수 값이 아니라 고정된 숫자 바이트 시퀀스를 표현하려는 것이기 때문이에요.

2진수와 8진수 리터럴도 지원돼요.

julia> x = 0b10
0x02

julia> typeof(x)
UInt8

julia> x = 0o010
0x08

julia> typeof(x)
UInt8

julia> x = 0x00000000000000001111222233334444
0x00000000000000001111222233334444

julia> typeof(x)
UInt128

16진수 리터럴과 마찬가지로, 2진수·8진수 리터럴은 부호 없는 정수 타입을 만들어요. 리터럴의 첫 자리가 0이 아니면 데이터 항목의 크기는 최소 필요 크기예요. 앞에 0이 있는 경우에는, 같은 길이이고 첫 자리가 1인 리터럴에 필요한 최소 크기로 크기가 결정돼요. 즉:

  • 0x10x12UInt8 리터럴,
  • 0x1230x1234UInt16 리터럴,
  • 0x123450x12345678UInt32 리터럴,
  • 0x1234567890x1234567890adcdefUInt64 리터럴 등이에요.

값에 기여하지 않는 앞쪽의 0도 저장 크기 결정에는 포함돼요. 그래서 0x01UInt8인 반면 0x0001UInt16이에요.

이 덕분에 사용자가 크기를 직접 조절할 수 있어요.

UInt128로 표현하기엔 너무 큰 정수를 담은 부호 없는 리터럴(0x로 시작)은 대신 BigInt 값을 만들어요. 이것은 부호 없는 타입은 아니지만, 그렇게 큰 정수 값을 표현할 수 있는 유일한 내장 타입이에요.

2진수·8진수·16진수 리터럴은 부호 없는 리터럴 바로 앞에 -를 붙여 부호를 줄 수 있어요. 이 경우 부호 없는 리터럴과 같은 크기의 부호 없는 정수를 만들되, 2의 보수(two's complement) 값을 가져요.

julia> -0x2
0xfe

julia> -0x0002
0xfffe

정수 같은 원시 숫자 타입의 최솟값과 최댓값은 typemintypemax 함수로 구할 수 있어요.

julia> (typemin(Int32), typemax(Int32))
(-2147483648, 2147483647)

julia> for T in [Int8,Int16,Int32,Int64,Int128,UInt8,UInt16,UInt32,UInt64,UInt128]
           println("$(lpad(T,7)): [$(typemin(T)),$(typemax(T))]")
       end
   Int8: [-128,127]
  Int16: [-32768,32767]
  Int32: [-2147483648,2147483647]
  Int64: [-9223372036854775808,9223372036854775807]
 Int128: [-170141183460469231731687303715884105728,170141183460469231731687303715884105727]
  UInt8: [0,255]
 UInt16: [0,65535]
 UInt32: [0,4294967295]
 UInt64: [0,18446744073709551615]
UInt128: [0,340282366920938463463374607431768211455]

typemintypemax이 반환하는 값은 항상 주어진 인자 타입이에요. (위 표현식은 아직 소개하지 않은 for 루프, 문자열, 보간 같은 기능을 사용하지만, 프로그래밍 경험이 조금 있는 분이라면 이해하기 어렵지 않을 거예요.)

오버플로우 동작

Julia에서는 어떤 타입의 최대 표현 가능 값을 넘기면 감싸기(wraparound) 동작이 일어나요.

julia> x = typemax(Int64)
9223372036854775807

julia> x + 1
-9223372036854775808

julia> x + 1 == typemin(Int64)
true

Julia의 정수 타입 연산은 본질적으로 모듈러 산술을 수행해서, 현대 컴퓨터 하드웨어의 정수 산술 특성을 그대로 반영해요. 오버플로우가 발생할 가능성이 있는 상황이라면, 그로 인한 감싸기 효과가 없는지 명시적으로 확인하는 게 중요해요. Base.Checked 모듈은 오버플로우 검사가 달린 산술 연산 모음을 제공하며, 오버플로우가 발생하면 오류를 발생시켜요. 어떤 상황에서도 오버플로우를 용납할 수 없는 경우에는, 임의 정밀도 산술에서 다루는 BigInt 타입을 쓰는 게 좋아요.

오버플로우 동작과 해결 방법의 예는 다음과 같아요.

julia> 10^19
-8446744073709551616

julia> big(10)^19
10000000000000000000

나눗셈 오류

정수 나눗셈(div 함수)에는 두 가지 예외적인 경우가 있어요. 0으로 나누는 경우와, 가장 작은 음수(typemin)를 -1로 나누는 경우예요. 두 경우 모두 DivideError를 던져요. 나머지와 모듈로 함수(remmod)는 두 번째 인자가 0일 때 DivideError를 던져요.

부동소수점 수

부동소수점 리터럴은 필요한 경우 E-표기법(지수 표기)을 사용해 표준 형식으로 표현돼요.

julia> 1.0
1.0

julia> 1.
1.0

julia> 0.5
0.5

julia> .5
0.5

julia> -1.23
-1.23

julia> 1e10
1.0e10

julia> 2.5e-4
0.00025

위 결과는 모두 Float64 값이에요. 리터럴 Float32 값은 e 대신 f를 써서 입력할 수 있어요.

julia> x = 0.5f0
0.5f0

julia> typeof(x)
Float32

julia> 2.5f-4
0.00025f0

값을 Float32로 변환하는 것도 쉬워요.

julia> x = Float32(-1.5)
-1.5f0

julia> typeof(x)
Float32

16진수 부동소수점 리터럴도 유효하지만, Float64 값으로만 가능해요. 밑 2 지수 앞에는 p가 붙어요.

julia> 0x1p0
1.0

julia> 0x1.8p3
12.0

julia> x = 0x.4p-1
0.125

julia> typeof(x)
Float64

반정밀도 부동소수점 수(Float16)도 모든 플랫폼에서 지원돼요. 이 숫자 형식을 지원하는 하드웨어에서는 네이티브 명령어를 쓰고, 그렇지 않은 경우에는 중간 계산에 Float32를 사용해 소프트웨어로 구현돼요. 내부 구현 세부사항으로는, 이는 LLVM의 half 타입을 사용해 이뤄져요. 이는 GCC가 C/C++ 코드에 적용하는 -fexcess-precision=16 플래그와 비슷하게 동작해요.

julia> sizeof(Float16(4.))
2

julia> 2*Float16(4.)
Float16(8.0)

밑줄 _은 숫자 구분 기호로 쓸 수 있어요.

julia> 10_000, 0.000_000_005, 0xdead_beef, 0b1011_0010
(10000, 5.0e-9, 0xdeadbeef, 0xb2)

부동소수점 0

부동소수점 수에는 두 개의 0이 있어요. 양의 0과 음의 0이에요. 둘은 서로 같지만 이진 표현은 달라요. bitstring 함수로 확인해볼 수 있어요.

julia> 0.0 == -0.0
true

julia> bitstring(0.0)
"0000000000000000000000000000000000000000000000000000000000000000"

julia> bitstring(-0.0)
"1000000000000000000000000000000000000000000000000000000000000000"

특수 부동소수점 값

실수 직선의 어떤 점에도 해당하지 않는, 표준으로 규정된 부동소수점 값이 세 가지 있어요.

Float16 Float32 Float64 이름 설명
Inf16 Inf32 Inf 양의 무한대 모든 유한 부동소수점 값보다 큰 값
-Inf16 -Inf32 -Inf 음의 무한대 모든 유한 부동소수점 값보다 작은 값
NaN16 NaN32 NaN 숫자가 아님 (not a number) 어떤 부동소수점 값과도 ==가 아닌 값 (자기 자신 포함)

이 비유한 부동소수점 값들이 서로 그리고 다른 부동소수점과 어떻게 정렬되는지 더 알고 싶으면 숫자 비교를 참고하세요. IEEE 754 표준에 따르면, 이 값들은 특정 산술 연산의 결과로 나와요.

julia> 1/Inf
0.0

julia> 1/0
Inf

julia> -5/0
-Inf

julia> 0.000001/0
Inf

julia> 0/0
NaN

julia> 500 + Inf
Inf

julia> 500 - Inf
-Inf

julia> Inf + Inf
Inf

julia> Inf - Inf
NaN

julia> Inf * Inf
Inf

julia> Inf / Inf
NaN

julia> 0 * Inf
NaN

julia> NaN == NaN
false

julia> NaN != NaN
true

julia> NaN < NaN
false

julia> NaN > NaN
false

typemintypemax 함수는 부동소수점 타입에도 적용돼요.

julia> (typemin(Float16),typemax(Float16))
(-Inf16, Inf16)

julia> (typemin(Float32),typemax(Float32))
(-Inf32, Inf32)

julia> (typemin(Float64),typemax(Float64))
(-Inf, Inf)

머신 엡실론

대부분의 실수는 부동소수점 수로 정확히 표현할 수 없어요. 그래서 여러 목적에서, 인접한 두 표현 가능 부동소수점 수 사이의 거리를 아는 것이 중요해요. 이를 흔히 머신 엡실론(machine epsilon)이라고 불러요.

Julia는 1.0과 그 다음으로 큰 표현 가능한 부동소수점 값 사이의 거리를 알려주는 eps를 제공해요.

julia> eps(Float32)
1.1920929f-7

julia> eps(Float64)
2.220446049250313e-16

julia> eps() # eps(Float64)와 같음
2.220446049250313e-16

이 값들은 각각 Float32Float64 값으로 2.0^-232.0^-52예요. eps 함수는 부동소수점 값을 인자로 받을 수도 있는데, 그 값과 다음 표현 가능 부동소수점 값 사이의 절대 차이를 줘요. 즉 eps(x)x와 같은 타입의 값을 반환해서, x + eps(x)x보다 큰 다음 표현 가능 부동소수점 값이 돼요.

julia> eps(1.0)
2.220446049250313e-16

julia> eps(1000.)
1.1368683772161603e-13

julia> eps(1e-27)
1.793662034335766e-43

julia> eps(0.0)
5.0e-324

인접한 두 표현 가능 부동소수점 수 사이의 거리는 일정하지 않아요. 값이 작을수록 거리가 작고, 값이 클수록 거리가 커져요. 다시 말해, 표현 가능한 부동소수점 수는 실수 직선에서 0 근처가 가장 밀집해 있고, 0에서 멀어질수록 지수적으로 성겨져요. 정의에 따라 eps(1.0)eps(Float64)와 같아요. 1.0이 64비트 부동소수점 값이기 때문이죠.

Julia는 또한 nextfloatprevfloat 함수를 제공해요. 각각 인자보다 크거나 작은 다음 표현 가능 부동소수점 수를 반환해요.

julia> x = 1.25f0
1.25f0

julia> nextfloat(x)
1.2500001f0

julia> prevfloat(x)
1.2499999f0

julia> bitstring(prevfloat(x))
"00111111100111111111111111111111"

julia> bitstring(x)
"00111111101000000000000000000000"

julia> bitstring(nextfloat(x))
"00111111101000000000000000000001"

이 예시는 일반 원리를 잘 보여줘요. 인접한 표현 가능 부동소수점 수는 인접한 이진 정수 표현도 가져요.

반올림 모드

숫자가 정확한 부동소수점 표현을 갖지 못하면, 적절한 표현 가능 값으로 반올림해야 해요. 그런데 이 반올림이 수행되는 방식은, IEEE 754 표준에 제시된 반올림 모드에 따라 필요에 따라 바꿀 수 있어요.

항상 쓰이는 기본 모드는 RoundNearest예요. 가장 가까운 표현 가능 값으로 반올림하고, 정확히 중간일 때는 최하위 비트가 짝수인 값 쪽으로 반올림해요.

배경과 참고 자료

부동소수점 산술에는 저수준 구현 세부사항에 익숙하지 않은 사용자에게 놀라움을 주는 미묘한 점이 많아요. 하지만 이런 미묘한 점들은 대부분의 과학 계산 서적과 아래 참고 자료에 자세히 설명돼 있어요.

임의 정밀도 산술

임의 정밀도의 정수와 부동소수점 수로 계산하기 위해, Julia는 각각 GNU Multiple Precision Arithmetic Library (GMP)GNU MPFR Library를 감싸요. 임의 정밀도 정수와 부동소수점 수를 위해 Julia에서 쓸 수 있는 타입이 BigIntBigFloat예요.

원시 숫자 타입에서 이 타입을 만들기 위한 생성자가 있고, 문자열 리터럴 @big_strparseAbstractString에서 만들 수도 있어요. BigInt는 다른 내장 정수 타입에 비해 너무 클 때 정수 리터럴로 입력할 수도 있어요. Base에는 부호 없는 임의 정밀도 정수 타입이 없어서(BigInt가 대부분의 경우 충분하죠), 16진수·8진수·2진수 리터럴도 (10진수 리터럴에 더해) 사용할 수 있어요.

일단 만들어지면, Julia의 타입 승격·변환 메커니즘 덕분에 다른 모든 숫자 타입과 산술에 참여할 수 있어요.

julia> BigInt(typemax(Int64)) + 1
9223372036854775808

julia> big"123456789012345678901234567890" + 1
123456789012345678901234567891

julia> parse(BigInt, "123456789012345678901234567890") + 1
123456789012345678901234567891

julia> string(big"2"^200, base=16)
"100000000000000000000000000000000000000000000000000"

julia> 0x100000000000000000000000000000000-1 == typemax(UInt128)
true

julia> 0x000000000000000000000000000000000
0

julia> typeof(ans)
BigInt

julia> big"1.23456789012345678901"
1.234567890123456789010000000000000000000000000000000000000000000000000000000004

julia> parse(BigFloat, "1.23456789012345678901")
1.234567890123456789010000000000000000000000000000000000000000000000000000000004

julia> BigFloat(2.0^66) / 3
2.459565876494606882133333333333333333333333333333333333333333333333333333333344e19

julia> factorial(BigInt(40))
815915283247897734345611269596115894272000000000

다만 위 원시 타입들과 BigInt/BigFloat 사이의 타입 승격은 자동이 아니고 명시적으로 지정해야 해요.

julia> x = typemin(Int64)
-9223372036854775808

julia> x = x - 1
9223372036854775807

julia> typeof(x)
Int64

julia> y = BigInt(typemin(Int64))
-9223372036854775808

julia> y = y - 1
-9223372036854775809

julia> typeof(y)
BigInt

BigFloat 연산의 기본 정밀도(가수 비트 수)와 반올림 모드는 setprecisionsetrounding을 호출해 전역적으로 바꿀 수 있어요. 이후의 모든 계산이 이 변경을 반영해요. 또는 같은 함수를 do 블록과 함께 써서 특정 코드 블록 실행 동안에만 정밀도나 반올림을 바꿀 수도 있어요.

julia> setrounding(BigFloat, RoundUp) do
           BigFloat(1) + parse(BigFloat, "0.1")
       end
1.100000000000000000000000000000000000000000000000000000000000000000000000000003

julia> setrounding(BigFloat, RoundDown) do
           BigFloat(1) + parse(BigFloat, "0.1")
       end
1.099999999999999999999999999999999999999999999999999999999999999999999999999986

julia> setprecision(40) do
           BigFloat(1) + parse(BigFloat, "0.1")
       end
1.1000000000004

setprecision이나 setrounding과, big"0.3" 같은 big 문자열 리터럴에 쓰이는 매크로인 @big_str의 관계는 직관적이지 않을 수 있어요. @big_str이 매크로이기 때문이죠. 자세한 내용은 @big_str 문서를 참고하세요.

숫자 리터럴 계수

흔한 수치 공식과 표현식을 더 명확하게 만들기 위해, Julia는 변수 바로 앞에 숫자 리터럴이 와서 곱셈을 암시하도록 허용해요. 이렇게 하면 다항식 표현을 훨씬 깔끔하게 쓸 수 있어요.

julia> x = 3
3

julia> 2x^2 - 3x + 1
10

julia> 1.5x^2 - .5x + 1
13.0

지수 함수를 쓰는 것도 더 우아해져요.

julia> 2^2x
64

숫자 리터럴 계수의 우선순위는 부정(negation) 같은 단항 연산자보다 살짝 낮아요. 그래서 -2x(-2) * x로, √2x(√2) * x로 파싱돼요. 하지만 숫자 리터럴 계수는 거듭제곱과 결합할 때는 단항 연산자처럼 파싱돼요. 예를 들어 2^3x2^(3x)로, 2x^32*(x^3)으로 파싱돼요.

숫자 리터럴은 괄호로 싼 표현식의 계수로도 동작해요.

julia> 2(x-1)^2 - 3(x-1) + 1
3

암시적 곱셈에 쓰인 숫자 리터럴 계수의 우선순위는 곱셈(*)이나 나눗셈(/, \, //) 같은 다른 이항 연산자보다 높아요. 그래서 예를 들어 1 / 2im-0.5im과 같고, 6 // 2(2 + 1)1 // 1과 같아요.

추가로, 괄호로 싼 표현식도 변수의 계수로 쓰여, 그 표현식과 변수의 곱을 암시할 수 있어요.

julia> (x-1)x
6

다만 괄호로 싼 두 표현식을 나란히 붙이는 것이나, 변수를 괄호로 싼 표현식 앞에 두는 것으로는 곱셈을 암시할 수 없어요.

julia> (x-1)(x+1)
ERROR: MethodError: objects of type Int64 are not callable

julia> x(x+1)
ERROR: MethodError: objects of type Int64 are not callable

두 표현식 모두 함수 적용으로 해석돼요. 숫자 리터럴이 아닌 어떤 표현식이라도 괄호 바로 뒤에 오면, 괄호 안의 값들에 적용되는 함수로 해석되죠 (함수 참고). 그래서 두 경우 모두 왼쪽 값이 함수가 아니기 때문에 오류가 발생해요.

위 문법 개선들은 흔한 수학 공식을 쓸 때 생기는 시각적 잡음을 크게 줄여줘요. 숫자 리터럴 계수와 곱해지는 식별자·괄호 표현식 사이에는 공백이 있으면 안 된다는 점을 기억하세요.

문법 충돌

나란히 붙는 리터럴 계수 문법은 일부 숫자 리터럴 문법과 충돌할 수 있어요. 16진수·8진수·2진수 정수 리터럴과 부동소수점 리터럴의 공학 표기법이 그 예예요. 문법적 충돌이 생기는 상황을 볼게요.

  • 16진수 정수 리터럴 표현식 0xff는 숫자 리터럴 0과 변수 xff의 곱으로 해석될 수 있어요. 0o777이나 0b01001010 같은 8진수·2진수 리터럴에서도 비슷한 모호함이 생겨요.
  • 부동소수점 리터럴 표현식 1e10은 숫자 리터럴 1과 변수 e10의 곱으로 해석될 수 있어요. 같은 의미의 E 형식도 마찬가지예요.
  • 32비트 부동소수점 리터럴 표현식 1.5f22는 숫자 리터럴 1.5와 변수 f22의 곱으로 해석될 수 있어요.

모든 경우에 모호함은 숫자 리터럴 해석 쪽으로 해결돼요.

  • 0x/0o/0b로 시작하는 표현식은 항상 16진수/8진수/2진수 리터럴이에요.
  • 숫자 리터럴 다음에 eE가 오는 표현식은 항상 부동소수점 리터럴이에요.
  • 숫자 리터럴 다음에 f가 오는 표현식은 항상 32비트 부동소수점 리터럴이에요.

E와 달리 F는 그냥 또 하나의 문자라서, 숫자 리터럴에서 f처럼 동작하지 않아요. 그래서 숫자 리터럴 다음에 F가 오는 표현식은 그 숫자 리터럴과 변수의 곱으로 해석돼요. 예를 들어 1.5F221.5 * F22와 같아요.

리터럴 0과 1

Julia는 주어진 타입이나 변수의 타입에 해당하는 리터럴 0과 1을 반환하는 함수를 제공해요.

함수 설명
zero(x) 타입 x 또는 변수 x의 타입에 해당하는 리터럴 0
one(x) 타입 x 또는 변수 x의 타입에 해당하는 리터럴 1

이 함수들은 숫자 비교에서 불필요한 타입 변환의 오버헤드를 피하는 데 유용해요.

예시:

julia> zero(Float32)
0.0f0

julia> zero(1.0)
0.0

julia> one(Int32)
1

julia> one(BigFloat)
1.0

더 알아보기