본문 바로가기

개발공부/C

부동소수점의 한계

본 게시글은 홍정모교수님의 '따라하며 배우는 C언어'에서 학습한 내용을 정리한 글임을 알립니다.

int main()
{
	//round-off error(ex1)
    float a, b;
    a = 1.0e20f + 1.0f;
    b = a - 1.0e20f;
    printf("%f\n", b);
}
0.000000

a가 너무 크다보니까 범위를 초과했음

보동소수점이 메모리를 사용하는데에 있어서 구조적인 문제때문에 발생하는 한계이다.

int main()
{
	//round-off error (ex2)
    float a = 0.0f;
    int i = 0;
    
    for(i = 0; i<100; i++)
    {
    	a = a + 0.1f;
    }
    printf("%f\n", a);
}
0.999999

1.000000라는 값이 나올거라는 예상과는 달리 그 보다 0.000001이작은 값이 나왔다.

0.25(2의 -2제곱)씩 더했다면 정확한 값을 계산해서 나왔을테지만 매번 이렇게 값을 생각하면서 쓰기가 어렵다.

#include <stdio.h>
#include <float.h>

int main()
{
	//overflow
    float max = 3.402823466e+38F; //float이 가질수 있는 가장 큰 숫자
    printf("%f\n", max);
    
    max = max * 100.0f;
    printf("%f\n", max);
}
340282346638528859811704183484516925440.000000
inf

  float에서 10진수의 유효숫자를 보장해주는 것은 6자리까지라서 340282까지는 믿을 수 있지만

그 이후의 숫자는 맞을 수도 있고 아닐 수도 있다.

다음 줄에는 무한대를 나타내는 숫자를 출력시켰다.

#include <stdio.h>
#include <float.h>

int main()
{
	//underflow
    float f = 1.401298464e-45F;
    printf("%e\n", f);
    f = f / 100.0f;
    printf("%e\n", f);
    
    return 0;
}

float에서 표현할 수 있는 가장 작은 수 f  (min  positive value)

수학에서 실수는 무한소까지를 포함하지만 컴퓨터는 한정된 메모리를 사용하는 자료형으로 흉내를 내고있기 때문에

무한히 작은 숫자를 흉내낼 수는 없다.

1.401298e-45
0.000000e+00

숫자 f가 0이 되었다.

이런 경우를 subnormal이라고 한다.

#include <stdio.h>
#include <float.h>

int main()
{
	float f = 104.0f;
	printf("%f\n", f);
	f = f / 0.0f;
	printf("%f\n", f);
    
	return 0;
}
104.000000
inf

0 으로 나누어 보았다. 이 또한 불가능하다.

#include <stdio.h>
#include <float.h>
#include <math.h>

int main()
{
	float f = asinf(1.0f);
	printf("%f\n", f);
    
	f = asinf(2.0f);
	printf("%f\n", f);
    
	return 0;
}
1.570796
-nan(ind)

sin(x)의 치역은 -1<=sin(x)<=1이다.  

asin(x)은 sin(x)의 역함수이다.

그래서 asin(x)는 x값에 따른 라디안을 출력한다.

이 예제에서는 2.0의 값을 넣고 강행하면(수학적으로 존재하지않는 값을 강제로)

예상하지 못한 결과값이 출력된다.

'개발공부 > C' 카테고리의 다른 글

기호적상수와 전처리기  (0) 2019.10.15
sizeof 연산자  (0) 2019.10.15
C언어 문자열 출력(직관적)  (0) 2019.10.15
고정너비정수  (0) 2019.10.15
프로그래밍 직관적으로 보기  (0) 2019.10.14