При использовании чисел с плавающей запятой реляционные операторы имеют значения, но их значения не обязательно совпадают с тем, как ведут себя реальные числа.
Если значения с плавающей точкой используются для представления реальных чисел (их нормального назначения), операторы, как правило, ведут себя следующим образом:
x > y
и x >= y
как следует, что числовое количество, которое x
предполагается представляют, вероятно, больше, чем y
, и в худшем случае, вероятно, не намного меньше y
.
x < y
и x <= y
как следует, что числовое количество, которое x
должен представлять, вероятно, меньше, чем y
, и в худшем случае, вероятно, не намного больше, чем y
.
x == y
означает, что числовые величины, которые x
и y
представляют неотличимы друг от друга
Обратите внимание, что, если x
имеет тип float
и y
имеет тип double
, вышеуказанные значения будут достигнуты если аргумент double
отличен до float
. Тем не менее, при отсутствии конкретного приведения, C и C++ (а также многие другие языки) преобразуют операнд float
в double
перед выполнением сравнения. Такое преобразование значительно уменьшит вероятность того, что операнды будут сообщены «неразличимыми», но значительно увеличит вероятность того, что сравнение даст результат, противоположный тому, что на самом деле указывают предполагаемые цифры. Рассмотрим, например,
float f = 16777217;
double d = 16777216.5;
Если оба операнда приводятся к float
, сравнение покажет, что значения неразличимы. Если их отличить до double
, сравнение будет указывать на то, что d
больше, даже если значение f
должно представлять немного больше. В качестве более крайнего примера:
float f = 1E20f;
float f2 = f*f;
double d = 1E150;
double d2 = d*d;
Float f2
содержит лучшие float
представления 1E40. Double d2
содержит лучшее изображение double
1E400. Числовая величина, представленная d2 is hundreds of orders of magnitude greater than that represented by
f2 , but
(double) f2> d2 . By contrast, converting both operands to float would yield
f2 == (float) d2`, правильно сообщив, что значения несовместимы.
PS - Мне хорошо известно, что стандарты IEEE требуют, чтобы вычисления выполнялись так, как если бы значения с плавающей запятой представляли точную долю мощности двух фракций, но мало кто видел код float f2 = f1/10.0;
как «установить f2 на представимую мощность 2-й фракции, которая ближе всего к одной десятой единицы в f1 ". Цель кода - сделать f2 десятой частью f1. Из-за неточности код не может полностью выполнить эту цель, но в большинстве случаев более полезно рассматривать числа с плавающей запятой как представляющие фактические числовые величины, чем рассматривать их как долю мощности двух.
Нет ничего плохого в равенстве, сравнивающем значения с плавающей запятой как таковые. Проблема в том, что результат может не соответствовать ожиданиям. –