2017-01-17 3 views
1

Comparing Same Float Values In CСтранный выход при сравнении одинаковых значений поплавка?

strange output in comparison of float with float literal

Float addition promoted to double?


Я прочитал выше ссылки на плавающих точек, но даже получить странный вывод.

#include<stdio.h> 
int main() 
{ 
    float x = 0.5; 

    if (x == 0.5) 
     printf("IF"); 

    else if (x == 0.5f) 
     printf("ELSE IF"); 

    else 
     printf("ELSE"); 
} 

Теперь, в соответствии с правилами продвижения, не должны "ELSE IF" должен быть напечатан?

Но здесь печатает «IF»


EDIT: Это потому, что 0.5 = 0.1 в двоичной и все равно 0, после этого и потери точности, следовательно, никаких эффектов, поэтому сравнение IF возвращает true.

Если бы это было 0.1, 0.2, 0.3, 0.4, 0.6, 0.7 ...., то Else If блок возвращает true.


Извините, что задал один и тот же вопрос, потому что я прочитал из приведенных выше ссылок, которые не сравниваются с результатами сравнения.

Но, в чем причина этого неожиданного поведения?

+0

[Обычные правила арифметического преобразования] (http://en.cppreference.com/w/c/language/conversion#Usual_arithmetic_conversions) утверждает, что если один из операндов является «double», то другой операнд преобразуется в «двойной». Таким образом, условие 'x == 0.5' на самом деле' (double) x == 0.5', которое, конечно, верно. Однако из-за проблем с значениями с плавающей запятой на компьютерах (см., Например, [Является ли математика с плавающей запятой?] (Http://stackoverflow.com/questions/588004/is-floating-point-math-broken) для деталей), существует очень мало значений, для которых это верно. –

+0

Я все еще думаю, что это немного непонятно, что именно вы спрашиваете, но если я это правильно пойму (и пойду с ответом Герхарда), тогда да, вы правы. –

+0

@Someprogrammerdude Да, это именно то, что я делаю. Благодаря !! –

ответ

5

Номера с плавающей точкой никогда не точны.

Это утверждение неверно. Некоторые числа с плавающей запятой являются точными, например 1.0, 12345.0, 12345.5, -2.25. Все эти числа могут быть представлены как целые числа, полученные силой 2. Все числа, которые также не могут быть точными.

В вашем конкретном случае float x = 0.5 приводит к x, имеющему значение 1.00000000 * 2^-1. Когда вы сравниваете это с double 0.5, оба операнда преобразуются в double, поэтому сравнение становится 1.000000000000000 * 2^-1 == 1.000000000000000 * 2^-1, что преуспевает.

Для float x = 0.1, это выглядит по-другому.Значение сохраняется как 1.01010101 * 2^-3 (или аналогичный). Обратите внимание, что это уже неточно. Когда вы сравниваете это с double 0.1, поплавок продолжается с нулями в конце, сравнение становится 1.010101010000000 * 2^-3 == 1.010101010101010 * 2^-3, что не получается.

+0

Спасибо! Получил то, что искал! Но я не могу его выдвинуть. –

+3

Я бы сказал, что все числа с плавающей запятой точны. Он выражает их в десятичной нотации, что неточно. Проблема заключается не в числах, проблема в их преобразовании в/из десятичных строк. Если бы мы только выражали целые числа как доли 3, они были бы «неточными». – Art

-1

В первом заявлении if оценивается true, поэтому печатается IF. Другие выражения даже не проверяются.

+0

Я думаю, что ОП это понимает. – Stargateur

+0

Ссылки, которые он добавил, указывают на то, что его фактический вопрос: _why_ условие оценивает 'TRUE'. – Gerhardh

5

Как вы прочли ссылки на проблемы с типами и сравнениями с плавающей точкой, вы, вероятно, ожидаете, что округление округляется во время преобразования, и, следовательно, сравнение не получится. Но 0.5 - это сила 2 и может быть представлена ​​идеально без какого-либо округления в переменной типа float или double. Поэтому сравнение приводит к TRUE.

После того, как вы отредактировали ваш вопрос: Да, если вы приняли 0,1 или одно из других значений, о которых вы упомянули, вы должны столкнуться с частью else.

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