C- Точность с плавающей точкой - PullRequest
1 голос
/ 06 марта 2012

У меня есть программа:

int main() 
{   
        float f = 0.0f;  
        int i;  

        for (i = 0 ; i < 10 ; i++) 
                f = f + 0.1f; 

        if (f == 1.0f) 
                printf("f is 1.0 \n"); 
        else 
                printf("f is NOT 1.0\n"); 

        return 0; 
} 

Он всегда печатает f is NOT 1.0. Я понимаю, что это связано с точностью с плавающей запятой в C. Но я не уверен, где именно это происходит. Может кто-нибудь объяснить мне, почему он не печатает другую строку?

Ответы [ 4 ]

4 голосов
/ 06 марта 2012

Двоичная с плавающей запятой не может точно представлять значение 0.1, потому что ее двоичное расширение не имеет конечного числа цифр (точно так же, как десятичное расширение 1/7 - нет).

двоичное расширение 0,1 равно

0.000110011001100110011001100...

При усечении до IEEE-754 с одинарной точностью это примерно 0.100000001490116119 в десятичном виде.Это означает, что каждый раз, когда вы добавляете значение «почти 0,1» к своей переменной, вы накапливаете небольшую ошибку - поэтому окончательное значение немного выше, чем 1.0.

2 голосов
/ 06 марта 2012

Для чисел с плавающей запятой вы всегда должны использовать значение epsilon при сравнении:

#define EPSILON 0.00001f

inline int floatsEqual(float f1, float f2)
{
    return fabs(f1 - f2) < EPSILON; // or fabsf
}
2 голосов
/ 06 марта 2012

Это равносильно добавлению 0,33 вместе 3 раза (0,99) и удивлению, почему оно не равно 1,0.

Возможно, вы захотите прочитать Что должен знать каждый программист об арифметике с плавающей запятой

2 голосов
/ 06 марта 2012

Вы не можете сравнивать поплавки, как это.Вам нужно определить порог и сравнить на основе этого. Это сообщение в блоге объясняет

...