2016-09-21 1 views
4
#include<stdio.h> 

void main() 
{ 
    float a = 2.3; 
    if(a == 2.3) { 
     pritnf("hello"); 
    } 
    else { 
     printf("hi"); 
    } 
} 

Он печатает «hi» на выходе, или мы можем сказать, что если условие получает ложное значение.Почему if (a == 2.3) оценивает значение false, когда float a = 2.3

#include<stdio.h> 

void main() 
{ 
    float a = 2.5; 
    if(a == 2.5) 
     printf("Hello"); 
    else 
     printf("Hi"); 
} 

Он печатает привет.

+3

@dbush Я не согласен с этим обманом. Предполагаемый обман - это то, что вычисление с плавающей точкой * является потенциально неточным, в то время как этот вопрос касается констант 'float' или' double'. Такая же проблема возникла бы, если 'a' был' short' или 'char', который не мог бы представлять целочисленную константу. – EOF

+0

Так почему это происходит ??? – Hariom

+2

Прочитайте http://floating-point-gui.de/ (и этот URL-адрес достаточно важен для запоминания) –

ответ

12

Переменная a - это float, которая имеет некоторое значение, близкое к математическому значению 2.3.

буквального 2.3 является double, что также имеет некоторое значение, близкое к значению математического 2.3, а потому, что double имеет большую точность, чем float, это может быть другое значение от значения a. Оба float и double могут представлять только конечное число значений, поэтому обязательно должны быть математические действительные числа, которые не могут быть представлены точно одним из этих двух типов.

Для сравнения a == 2.3, левый операнд повышается от float до double. Это продвижение является точным и сохраняет ценность (как и все рекламные акции), но, как обсуждалось выше, это значение может отличаться от значения в литерале 2.3.

Чтобы сделать сравнение между поплавками, вы можете использовать соответствующий поплавок буквальный:

assert(a == 2.3f); 
//   ^
+0

в случае 2.5 он вычисляет его true ?? Является ли это специфическим компилятором? – Hariom

+0

Можете ли вы привести часть стандарта ISO C, которая гарантирует такое поведение? (Я знаю, что есть один.) – Diti

+3

Вернее ... не используйте '==' для значений с плавающей запятой. – pmg

3

2.3 с двоичным представлением является 01000000000100110011001100110011... , так что вы не в состоянии установить поплавок точно 2.3 с двойной точностью вы получить что-то подобное: 2.299999952316284

вы преобразованы двойной плавать, когда вы писали:

float a = 2.3; 

КРП проверяет float a равна double 2.299999952316284

вы должны написать:

float a = 2.3f; 

и вы можете проверить:

if (a == 2.3f) { 
    ... 
} 

я предпочел бы проверить с:

if (fabs(a - 2.3f) < 0.00001) { 
    ... 
} 

2.5 представлена ​​битов: 01000000001000000000000000000000

РЕДАКТИРОВАТЬ:fabs является частью <math.h> или <cmath>

прочитать: article

+0

Реализация, которая использует десятичные поплавки, безусловно, может точно представлять как 2.3, так и 2.5. В конечном итоге это определяется реализацией. Важно то, что * некоторые * значения не могут быть представлены точно. –

+0

no 2.3 потребует бесконечного количества бит. Язык C никогда не использовал десятичное представление float, когда вы печатаете 2.3, он покажет вам округленное число. –

+3

@ DombiSzabolcs: C11 проект стандарта n1570: * 5.2.4.2.2 Характеристики плавающих типов Характеристики плавающих типов определяются в терминах модели, которая описывает представление чисел и значений с плавающей запятой , которые предоставляют информацию о a арифметика с плавающей запятой реализации. 21) Следующие параметры используются для определяют модель для каждого типа с плавающей запятой: [...] b base или radix представления экспоненты (целое число> 1) * Нет требования для 'b' быть неравным с' 10 '. – EOF

0

значения Сравнение с плавающей точкой не так просто, как может показаться, взгляните на Most effective way for float and double comparison.

Все это сводится к тому, что числа с плавающей запятой не являются точными (хорошо больше всего нет). Обычно вы сравните 2 поплавки, позволяя окно небольшой ошибки (эпсилон):

if(fabs(a - 2.3f) < epsion) { ... } 

где эпсилон достаточно мал для расчета, но не слишком мало (больше, чем Machine epsilon).

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