В стандартной библиотеке C есть: isgreater, isgreaterequal, isless, islessequal, islessgreater, isunordered. И почему в стандартной библиотеке C нет равенства? Это должно быть легко реализовать следующим образом:
bool isequal(float x, float y)
{
return !isunordered(x, y) && isgreaterequal(x, y) && !isgreater(x, y);
}
@WeatherVane: Это не имеет отношения к этому вопросу. Эти макросы предназначены для облегчения упорядочивания, например, сортировки. Они не предназначены для проведения какого-либо «приблизительного» сравнения. Если бы в этих макросах предполагалось какое-то «приблизительное» сравнение, это затронуло бы их все, а не только isequal
.
Возможность упорядочить вещи — это другой класс проблем, чем возможность проверить, совпадают ли два предмета.
Я думаю, что в большинстве случаев вам не нужно, чтобы они были абсолютно равными, и вы не можете ожидать, что они будут точно равными. Вы можете просто увидеть такие случаи, как 0.03 + 0.01 + 0.02 != 0.03 + 0.02 + 0.01
. В большинстве случаев то, что вы проверяете, если abs(d1 - d2) < epsilon
Я думаю, это потому, что эти макросы определены как «тихие» (не вызывающие исключений) аналоги обычных операторов отношений, в то время как ==
все равно молчит. Сказал, что есть функция iseqsig
, предложенная библиотекой GNU, которая делает противоположное - ведет себя как ==
, но выдает исключение: gnu.org/software/libc/manual/html_node/…
В обосновании C99 V5.10 объясняется, что эти макросы были добавлены в язык с единственной целью обеспечить безопасность и не вызывать исключений с плавающей запятой, как это могли бы делать соответствующие операторы:
Операторы отношения (
<
,<=
,>=
,>
), но не операторы равенства (==
и!=
), может вызывать исключения с плавающей запятой, когда одним из операндов являетсяNaN
(как индикатор ошибки для программ, написанных без учета NaN). Существует потребность в сравнениях, которые гарантированно [sic] не вызовут каких-либо исключений с плавающей запятой; это также является требованием [sic] стандарта IEC-60559. Вот почемуisgreater
,isgreaterequal
,isless
,islessequal
, Были изобретены макросыislessgreater
иisunordered
, похожие на функции.
Я знаю, почему сейчас нет равенства. И я проверяю, что это действительно работает (как побочный эффект): bool isequal(float x, float y) { return !isunordered(x, y) && isgreaterequal(x, y) && !isgreater(x, y); }
Следует ли считать два примерно равных значения с плавающей запятой равными, зависит от контекста. Связанный: Всегда ли допустима операция с плавающей запятой ==?