2012-11-26 2 views
6

저는 C를 아주 초보자입니다. 그래서 작은 게임 데모를 쓸 때 정말 이상한 문제에 직면합니다.플로트는 0.1을 더하면 바뀌지 않습니다.

void testC() 
{ 
    float a = 825300160; 
    float b = a + 0.1; 
    assert(a != b); 
} 

위의 assert 문은 전달할 수 없습니다. 아주 이상한.
내 환경은 mac os ml입니다. gcc 4.2.1

+3

'float'는'825300160'과'825300160.1'을 구별하기에 충분한 정밀도를 가지고 있지 않습니다. – Mysticial

+1

부동 소수점 숫자에는 약 6 자리의 정밀도가 있습니다. (대신'double '을 시도하십시오.) –

+0

'float'은 보통 24 비트의 정밀도를 가지고 있습니다. 'a'는'2^29'보다 크고,'b <2^(- 3)'이므로'b'는'a'에 영향을 줄 수있는 몇 비트가 아닙니다. –

답변

8

float의 분수 부분은 23 비트로 구성됩니다. 825300160을 나타 내기 위해서는 30 비트가 필요하므로 숫자의 덜 중요한 부분은 삭제됩니다. .1를 추가하면 차이가되지 않습니다 - 변경할 수를 약 32을 추가해야합니다

float a = 825300160; 
float b = a + 31.5; 
assert(a != b); // No change is detected 
float c = a + 32; 
assert(a != c); // Change is detected 
+0

+1 부동 소수점에 대한 훌륭한 설명. 나는 이것이 부동 소수점 표준을 잘 알고 있었으면 좋겠다. – tjameson

+0

그래서이 문제가 발생하지 않도록 컴파일러에게 뭔가를 할 수 있습니다. 컴파일러가 같은 일을 다시 할 때 경고를 내린다는 뜻입니다. 아니면 그냥 float의 범위를 염두에 두어야하며 다시 일어나지 않도록해야합니다. 감사. –

+0

나는 전에 자바 프로그래머이기 때문에 컴파일러는 내 코드에서 작은 문제가 숨어 있더라도 컴파일을 허용하지 않을 것이다. 그래서 내가 C 코드를 작성할 때, 전에 생각조차하지 못했던 많은 문제에 직면하게 될 것입니다. –

6

부동 소수점 유형의 정밀도가 충분하지 않습니다. 당신이 실제로 0.1을 825300160만큼 큰 숫자로 구별 할 필요가 있다면, double을 사용하십시오.

1

this site으로 쇼를 A와 B 모두 IEEE 표준에

0 10011100 10001001100010001010011 

로 표현된다 float의 경우 첫 번째 비트가 부호이고 다음 8 개는 지수이며 나머지 23은 가수입니다. 지수가 너무 커서 차이를 나타내는 데 23 비트의 공간이 충분하지 않습니다.

관련 문제