부동소수점 리터럴
부동소수점 리터럴
실수값을 그대로 코드에 적어야 할 때가 있어요. 그런 값들을 부동소수점 리터럴(floating-point literal) 이라고 부르는데요, Go에서는 이걸 십진수로도, 16진수로도 쓸 수 있어요. 두 형태가 어떻게 생겼는지, 그리고 어떤 조합은 허용되고 어떤 조합은 안 되는지 하나씩 짚어볼게요.
출처: Go Specification
본문
부동소수점 리터럴은 하나의 부동소수점 상수를 십진수 또는 16진수로 나타낸 표현이에요.
십진 부동소수점 리터럴은 정수부(십진 숫자), 소수점, 소수부(십진 숫자), 지수부(e 또는 E 뒤에 선택적 부호와 십진 숫자)로 이루어져요. 정수부와 소수부 중 하나는 생략할 수 있고, 소수점과 지수부 중 하나도 생략할 수 있어요. 지수값 exp는 가수(정수부와 소수부)를 10exp배로 스케일해요.
16진 부동소수점 리터럴은 0x 또는 0X 접두어, 정수부(16진 숫자), 기수점, 소수부(16진 숫자), 지수부(p 또는 P 뒤에 선택적 부호와 십진 숫자)로 이루어져요. 정수부와 소수부 중 하나는 생략할 수 있고, 기수점도 함께 생략할 수 있지만 지수부는 반드시 필요해요. (이 문법은 IEEE 754-2008 §5.12.3에서 주어진 것과 일치해요.) 지수값 exp는 가수를 2exp배로 스케일해요 Go 1.13.
가독성을 위해 밑줄 문자 _를 base 접두어 뒤나 연속된 숫자 사이에 넣을 수 있는데요, 그런 밑줄은 리터럴 값에는 영향을 주지 않아요.
float_lit = decimal_float_lit | hex_float_lit .
decimal_float_lit = decimal_digits "." [ decimal_digits ] [ decimal_exponent ] |
decimal_digits decimal_exponent |
"." decimal_digits [ decimal_exponent ] .
decimal_exponent = ( "e" | "E" ) [ "+" | "-" ] decimal_digits .
hex_float_lit = "0" ( "x" | "X" ) hex_mantissa hex_exponent .
hex_mantissa = [ "_" ] hex_digits "." [ hex_digits ] |
[ "_" ] hex_digits |
"." hex_digits .
hex_exponent = ( "p" | "P" ) [ "+" | "-" ] decimal_digits .
위 문법이 실제로 어떻게 쓰이는지는 예시로 확인하는 게 빠르죠. 아래는 유효한 예와 그 값을 계산해 본 결과예요.
0.
72.40
072.40 // == 72.40
2.71828
1.e+0
6.67428e-11
1E6
.25
.12345E+5
1_5. // == 15.0
0.15e+0_2 // == 15.0
0x1p-2 // == 0.25
0x2.p10 // == 2048.0
0x1.Fp+0 // == 1.9375
0X.8p-0 // == 0.5
0X_1FFFP-16 // == 0.1249847412109375
0x15e-2 // == 0x15e - 2 (integer subtraction)
0x.p1 // invalid: mantissa has no digits
1p-2 // invalid: p exponent requires hexadecimal mantissa
0x1.5e-2 // invalid: hexadecimal mantissa requires p exponent
1_.5 // invalid: _ must separate successive digits
1._5 // invalid: _ must separate successive digits
1.5_e1 // invalid: _ must separate successive digits
1.5e_1 // invalid: _ must separate successive digits
1.5e1_ // invalid: _ must separate successive digits
좋은 예시도 보셨으니, 이제 헷갈리기 쉬운 지점 몇 개만 정리할게요.
- 십진 리터럴은 지수에
e/E를 쓰는데, 16진 리터럴은 반드시p/P를 써요. 그래서1p-2처럼p지수인데 가수가 16진이 아니면 오류가 되고, 반대로0x1.5e-2처럼 16진 가수에e지수를 붙이면 오류가 돼요. - 16진 리터럴은 지수부가 필수예요. 가수에 숫자가 없는
0x.p1은 물론, 지수까지 없으면 아예 성립이 안 되죠. - 밑줄은 연속된 숫자를 구분하는 역할만 해요. 그래서
1_.5,1._5,1.5e_1처럼 숫자 사이가 아닌 자리에_가 있으면 전부 오류예요. 0x15e-2를 주의하세요. 이건0x로 시작하지만e-2가 지수부가 아니라 정수 뺄셈으로 해석돼요. 그래서 값이0x15e - 2예요. 16진 지수부는p/P로만 붙기 때문이에요.
더 알아보기
- Go Specification - Constants — 부동소수점 리터럴이 나타내는 상수에 대한 설명이에요.
- Go Specification - Imaginary literals — 부동소수점 리터럴 뒤에
i를 붙여 허수부를 만드는 문법이에요. - Go 1.13 release notes — 16진 부동소수점 리터럴 문법이 추가된 버전이에요.