부동소수점 표현은 IEEE 754 표준에 따라 구현합니다.
1/3 = 0.33333....
이기 때문에 무한히 표현할 수 없습니다. 2진법을 쓰는 컴퓨터에서는 이를 표현하는 데 한계가 있습니다.
자세한 내용은 IEEE 754 표준안을 살펴 보아야 합니다.
https://ko.wikipedia.org/wiki/IEEE_754
2진수에서 숫자를 표현하는 방법에 대해서는 <컴퓨터 구조>를 공부하면 됩니다.
페터슨의 <컴퓨터 구조 및 설계> 3장을 참고하세요.
http://www.yes24.com/Product/Goods/16426341?scode=032&OzSrank=1
간단히 말해 현대 프로그래밍 언어는 대부분 IEEE 754 표준안에 따라 부동소수점 표현을 구현합니다.
부동소수점 포맷은 부호비트, 지수, 가수로 구성되어 있습니다.
이 표현법에 따르면 부동소수점에서 가장 작은 수는 1이나 -1이 아닙니다.
부동소수점 수에서는 표현 가능한 다음 부동소수점 값이 가장 작은 수가 될 것입니다. 이를 직접 입력하거나 계산하기는 어렵기 때문에 C 언어에서는 nextafterf 함수가 별도로 제공됩니다.
float f = FLT_MAX;
printf("FLT_MAX: %a\n", f);
float b = nextafterf(f, 0);
printf("number before FLT_MAX: %a\n", b);
이와 같은 코드를 실행해보면 알 수 있습니다.FLT_MAX: 0x1.fffffep+127
number before FLT_MAX: 0x1.fffffcp+127
float d = f - b; printf("difference: %a\n", d); printf("FLT_MAX + d: %a\n", f + d);
차이 값을 살펴보세요. 더하면 inf로 무한이 되고 오버플로가 발생합니다. 왜 이런 값이 되는지 알고 싶다면 컴퓨터 구조를 공부하고, IEEE 754에 따라 비트 패턴을 구하고 값으로 변환하면 됩니다. 컴퓨터 과학 전공이면 컴퓨터 구조 시간에 중간 고사로 반드시 하게 되어 있습니다.
difference: 0x1p+104
FLT_MAX + d: inf
대다수가 그러하듯이 시험이 끝나면 잊어버리고, 전공자나 비전공자나 이러한 표현은 잊어버립니다.
다만, 부동소수점은 비교할 수 없다는 것과 유효자릿수가 있다는 점만 기억하게 됩니다. 그럼에도 20년 동안 프로그래밍을 하는 데 아무 불편함이 없습니다.
FLT_MAX + 1과 FLT_MIN - 1로 오버플로와 언더플로가 발생하지 않는 건 부동소수점을 표현하는 IEEE 754 포맷에서는 1이 너무 작은 값이어서 그렇습니다. 오버플로와 언더플로를 일으키는 데 필요한 충분한 값은 nextafterf 함수로 구해서 써야 합니다. 사람이 손으로 직접 하기에는 복잡합니다.
주변에 전공자나 프로그래머가 있다면 IEEE 754 부동소수점에서 FLT_MAX와 FLT_MIN에 해당하는 비트 패턴을 쓸 수 있어? 라고 물어보시면 됩니다. 즉답할 수 있는 사람은 거의 없을 겁니다. 시험이 끝나면 잊어버리니까요.
초보자는 지나치게 디테일에 집착하기보단 프로그래밍을 익히는 게 더 중요합니다. 디테일은 컴퓨터 구조를 공부하면 되고, Verilog를 이용한 디지털 시스템 설계 및 실습을 공부하면 됩니다. 전공 과목에서 가능하면 피하고 싶다고 말하는 과목입니다. Verilog가 적성에 맞는다고 느끼면 컴퓨터 과학, 전자공학 전공 불문하고 대학교의 '반도체 설계 연구실'로 석사/박사 과정을 진학하면 됩니다.
C 언어를 빨리 끝내요!