2013-08-09 3 views
3

с помощью следующего кода,числа с плавающей точкой проверки равенства

#include <stdio.h> 

int main(void){ 
    float x; 
    x=(float)3.3==3.3; 
    printf("%f",x); 
    return 0; 
} 

выход составляет 0,00000

, но когда число 3.3 заменяется 3.5,

#include <stdio.h> 

int main(void){ 
    float x; 
    x=(float)3.5==3.5; 
    printf("%f",x); 
    return 0; 
} 

выход 1,0000

Почему разница в выходе?

+3

Почему бы хранить булев результат операции равенства в виде числа с плавающей точкой? –

+4

Также вы можете прочитать [Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). –

+0

И, в-третьих, узнайте разницу между 'float' и' double', как в общем, так и в литературе. –

ответ

4

== Выполняет проверку равенства. проверяет равенство являются проблематичными с поплавками (см http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm)

Итак, как только вы получите ложный и как только вы получите истинное (1)

Для более надежного способа сравнения поплавков см. - What is the most effective way for float and double comparison?

+0

Примечание: Брюс Доусон обновил свою запись для ссылки на запись в блоге (Сравнение чисел с плавающей запятой, издание 2012 года) [https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012 -издание/]. И связанный с ним SO Q & A на самом деле неполный в обработке сравнения с плавающей запятой. (Ни один ответ не является исчерпывающим при определении даже основных вопросов). – mctylr

9

вы должен понимать, что в C буква 3.3 имеет тип double. Преобразование double в float может потерять точность, поэтому сравнение 3.3F с 3.3 дает false. Для 3.5 преобразование без потерь, поскольку оба могут быть представлены точно, а сравнение дает true .

Это несколько связано с (в базе 10 вместо основания 2) сравнение

3.3333333 with 3.3333333333333333 (false) 
3.5000000 with 3.5000000000000000 (true) 
+1

Другая часть знания о том, что происходит, - это '(float) 3.Значение перед возвратом возвращается к 'double' перед сравнением. – caf

+0

@caf: Хорошо знать это, но это не имеет отношения к этому вопросу. Пока '==' возвращает true тогда и только тогда, когда левый операнд равен правильному операнду, не имеет значения, продвигает ли он один из операндов или реализует какое-то прямое сравнение. '(float) 3.3 == 3.3' возвратит тот же результат в любом случае. –

5

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

И в вашем случае, превращение double в float теряет некоторую точность.

Вы должны быть очень осторожны при сравнении плавающих точек.

Я предлагаю вам взглянуть на эту ссылку: What is the most effective way for float and double comparison?

Эта статья может помочь вам понять, почему он добавляет: http://www.cprogramming.com/tutorial/floating_point/understanding_floating_point_representation.html


Небольшое пояснение о числах с плавающей точкой, и почему это :

Номера с плавающей запятой, как правило, упакованы в компьютерную дату в виде знака , expone nt поле, и Значимость (мантисса), слева направо.

В принципе, можно сказать, что число с плавающей точкой:

number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits) 

Конечно, в зависимости от того, если вы используете поплавок или двойной, точность отличается:

  | Sign | Exponent | Significand | Total bits 
float  | 1 | 8  | 23   | 32 
Double | 1 | 11  | 52   | 64 

Здесь вы можете увидеть, почему вы можете потерять некоторые данные, конвертировав double в float.

В вашем случае, кажется, что компьютер способен точно вычислить 3.5, но не 3.3. Так или иначе, с формулой, мы можем предположить, что вы делаете что-то вроде:

3.3333333 == 3.333333333333333 // is false because of the precision 
3.5000000 == 3.500000000000000 // is true 

// I tried to match the precision of the float in the left 
// and the precision of the double on the right 
4

Разница заключается в том, что 3,5 может быть точно представлены в виде двоичного числа с плавающей точкой, в то время как 3,3 не может.

Поскольку математический 3.3 не может быть точно представлен, 3.3, как число двойной точности, является лучшим приближением, чем одноточное число (float)3.3, и поэтому имеет другое значение.

0

Why is there a difference in output?

Теоретический, но, вероятно, неудовлетворительный ответ носить Math/CS () шляпа:

  • Потому что числа с плавающей точкой являются конечными, и, следовательно, не равны R http://mathurl.com/mgwavz7 числа нас используйте математику (и большую часть реального мира).
  • Числа с плавающей точкой являются двоичными, в отличие от десятичной, так что некоторые фракции, которые являются конечными в десятичном представлении, но повторяют или трансцендентальное (как Pi http://mathurl.com/62kzla или основание натурального логарифма е) в двоичной системе (или Radix 2).

@Jens

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