2013-08-22 2 views
-2

Не удалось найти причину следующий фрагмент кода:Понимание поплавок переменной сравнения, если()

#include <stdio.h> 
int main() 
{ 
    float f = 0.1; 
    if (f == 0.1) 
     printf("True"); 
    else 
     printf("False"); 
    return 0; 
} 

Выход ложна.

#include <stdio.h> 
int main() 
{ 
    float f = 0.1; 
    if (f == (float)0.1) 
     printf("True"); 
    else 
     printf("False"); 
    return 0; 
} 

Теперь отображается правильный результат. В чем причина этого?

Также в чем причина такого поведения.

#include <stdio.h> 
main() 
{ 
    int n = 0, m = 0; 
     if (n > 0) 
      if (m > 0) 
        printf("True"); 
     else 
      printf("False"); 
} 
+7

Пожалуйста, никогда не сравнивайте числа с плавающей запятой для равенства. Числа с плавающей точкой почти никогда не сравниваются. – fuz

+1

Дублировать буквально десятки раз. –

+1

.. и тег C открывает сегодняшнее соревнование «раздражающего вопроса» со старой классикой. (кредит: [Martin James] (http://stackoverflow.com/users/758133/martin-james)) –

ответ

5

0.1 литерал double. Вы теряете точность здесь float f = 0.1;

Можно сказать, что мы теряем точность во время сравнения, так почему же не f == 0.1 правда в любом случае? Потому что float простирается до double, а не наоборот. В C меньшем типе всегда распространяется на более крупный.

Упрощенный ваш пример, мы можем сказать, что double(float(1.0)) != 1.0

Возможные решения:

  • использовать double вместо float как тип f.
  • использование брошено как в вашем примере 2
  • использование float литералов - заменить все 0.1 с 0.1f

Лучшим решением

Плавающих переменными точками имеет много проблем с сравнениями. Они, в том числе и этой, могут быть решены путем определения своей собственной функции сравнения:

bool fp_equal(double a, double b, double eps = FLT_EPSILON) { 
    return fabs(a - b) < fabs(eps * a); 
} 

Вторая часть вопроса:

Почему ответ является ложным, потому что else части всегда соответствует внутренний if блок.Таким образом, вы были сбиты с толку форматирования, код эквивалентен:

#include <stdio.h> 

int main() 
{ 
    int n = 0, m = 0; 
    if (n > 0) { 
     if (m > 0) { 
      printf("True"); 
     } 
     else { 
      printf("False"); 
     } 
    } 
} 
+0

Благодарим вас за быстрый и правильный ответ. – Megharaj

+0

Другим решением является использование плавающего литерала 'f',' float f = 0.1f; if (f == 0.1f) '... –

+0

@AlterMann, это написано в моем asnwer. Обратите внимание на 3-ю пулю. –

2

Ответ на ваш второй вопрос (третий пример):

По вашему отступом, код не делает то, что вы exepect это:

#include <stdio.h> 
main() 
{ 
    int n = 0, m = 0; 
     if (n > 0) 
      if (m > 0) 
       printf("True"); 
     else 
      printf("False"); 
} 

Здесь else принадлежит к внутреннему if, поэтому он равен

#include <stdio.h> 
main() 
{ 
    int n = 0, m = 0; 
     if (n > 0) { 
      if (m > 0) { 
       printf("True"); 
      } else { 
       printf("False"); 
      } 
     } 
} 

, но я думаю, что вы имели в виду:

#include <stdio.h> 
main() 
{ 
    int n = 0, m = 0; 
     if (n > 0) { 
      if (m > 0) { 
       printf("True"); 
      } 
     } else { 
      printf("False"); 
     } 
} 

Это хороший пример того, почему один должен alwys скобки пользователя в if отчетности.

+0

И правильный отступ. И тип возврата для 'main'. –

+0

@Ligthness совершенно правильный –

+0

@lngo спасибо. – Megharaj

Смежные вопросы