Могу ли я сравнить и добавить число с плавающей точкой к целому числу в C? - PullRequest
19 голосов
/ 17 апреля 2009

Могу ли я сравнить число с плавающей запятой с целым числом?

Будет ли число с плавающей точкой сравниваться с целыми числами в коде?

float f;     // f has a saved predetermined floating-point value to it  
if (f >=100){__asm__reset...etc}

Кроме того, я мог бы ...

float f;
int x = 100;
x+=f;

Я должен использовать значение с плавающей запятой f , полученное от системы координат ориентации, чтобы отрегулировать значение позиции x , которое управляет сигналом ШИМ для корректировки положения.

Ответы [ 9 ]

21 голосов
/ 17 апреля 2009

Первый будет работать нормально. 100 будет преобразовано в число с плавающей точкой, а IEE754 может представлять все целые числа в точности как числа с плавающей точкой, примерно до 2 23 .

Второй также будет работать, но сначала будет преобразован в целое число, поэтому вы потеряете точность (это неизбежно, если вы превращаете числа с плавающей точкой в ​​целые числа).

10 голосов
/ 17 апреля 2009

Поскольку вы определили себя как незнакомого с тонкостями чисел с плавающей запятой, я отошлю вас к этой прекрасной статье Дэвида Голдберга: Что должен знать каждый специалист по вычислительной технике об арифметике с плавающей точкой ( Перепечатка на Солнце).

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

Вопросы о точности, безусловно, верны. IEEE float эффективно имеет точность только 24 бита, что меньше 32-битного целого числа. Использование double для промежуточных расчетов приведет к тому, что все округления и потери точности будут преобразованы обратно в float или int.

8 голосов
/ 17 апреля 2009

Арифметика смешанного режима (арифметика между операндами разных типов и / или размеров) является законной, но хрупкой. Стандарт C определяет правила для продвижения типов, чтобы преобразовать операнды в общее представление. Автоматическое продвижение типов позволяет компилятору делать что-то разумное для операций в смешанном режиме, но «разумный» не обязательно означает «правильный».

Чтобы действительно знать, правильное ли поведение, вы должны сначала понять правила продвижения, а затем понять представление типов данных. В очень общие условия:

  • более короткие типы преобразуются в более длинные типы (float до double, short до int и т. Д.)
  • целочисленные типы преобразуются в типы с плавающей запятой
  • конверсии со знаком / без знака позволяют избежать потери данных (независимо от того, преобразуется ли подпись в без знака или наоборот зависит от размера соответствующих типов)

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

2 голосов
/ 17 апреля 2009

Можете ли вы сравнить число с плавающей точкой и целое число? Но проблема, с которой вы столкнетесь, заключается в точности. В большинстве реализаций C / C ++ float и int имеют одинаковый размер (4 байта) и дико разные уровни точности. Ни один тип не может содержать все значения другого типа. Поскольку один тип не может быть преобразован в другой тип без потери точности, а типы не могут быть сравнимы по натуре, выполнение сравнения без учета другого типа приведет к потере точности в некоторых сценариях.

То, что вы можете сделать, чтобы избежать потери точности, - это преобразовать оба типа в тип, который имеет достаточную точность для представления всех значений float и int. На большинстве систем double сделает именно это. Таким образом, следующее обычно делает сравнение без потерь

float f = getSomeFloat();
int i = getSomeInt();
if ( (double)i == (double)f ) { 
   ...
}
1 голос
/ 17 апреля 2009

Да, вы можете сравнивать их, вы можете делать с ними математику, не особенно заботясь о том, что есть, в большинстве случаев. Но только большинство. Большая ошибка в том, что вы можете проверить на f<i и т. Д., Но не должны проверять на f==i. Целое число и число с плавающей точкой, которые «должны» быть одинаковыми по значению, не обязательно идентичны.

1 голос
/ 17 апреля 2009

LHS определяет точность, Таким образом, если ваша LHS - int, а RHS - float, то это приводит к потере точности.

Также взгляните на FP, связанный CFAQ

0 голосов
/ 28 октября 2010

При этом нотация 1.0 относится к типу double, поэтому сравнение выполняется в два раза по правилам продвижения типов, как указано выше. 1.f или 1.0f имеет тип float, и сравнение было бы сделано в float. И это сработало бы так же, как мы сказали, что 2 ^ 23 первых целых числа представимы в float.

0 голосов
/ 17 апреля 2009

Да, и иногда это будет именно то, что вы ожидаете.

Как уже указывали другие, сработает сравнение, например, 1.0 == 1, потому что целое число 1 приведено к типу double (не float) до сравнения.

Однако других сравнений может не быть.

0 голосов
/ 17 апреля 2009

Да, все будет хорошо. В частности, int будет преобразован в float для целей преобразования. Во втором случае вам нужно привести к int, но в противном случае все будет в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...