Когда сравнение для равенства - это хорошо для использования '=='?

Когда сравнение для равенства - это хорошо для использования ==?

Например:

int a = 3;
int b = 4;

Если проверка равенство должна Вы использовать:

if (a == b)
{
     . . .
}

Ситуация изменилась бы, если бы числа с плавающей точкой использовались?

5
задан Brandon 11 February 2010 в 09:37
поделиться

6 ответов

' == ' идеально подходит для целочисленных значений.

Вы не должны сравнивать числа с плавающей запятой на равенство; используйте подход с допуском:

if (fabs(a - b) < tolerance)
{
   // a and b are equal to within tolerance
}
15
ответ дан 18 December 2019 в 06:34
поделиться

Re с плавающей запятой: да. Не используйте == для чисел с плавающей запятой (или ТОЧНО знайте, что вы делаете, если вы это делаете). Скорее используйте что-то вроде

if (fabs(a - b) < SOME_DELTA) {
  ...
}

РЕДАКТИРОВАТЬ: изменено abs () на fabs ()

3
ответ дан 18 December 2019 в 06:34
поделиться

Во многих классах, operator== обычно реализуется как (!(a < b || b < a)), поэтому вы должны продолжать и использовать ==. За исключением floats, как сказал выше Mitch Wheat.

2
ответ дан 18 December 2019 в 06:34
поделиться

При сравнении ints используйте ==. Использование "<" и ">" одновременно для проверки равенства int приводит к более медленному коду, так как требуется два сравнения вместо одного, что занимает двойное количество времени. (хотя, возможно, компилятор исправит это за вас, но вы не должны привыкать писать плохой код).

Помните, что ранняя оптимизация - это плохо, но ранний неэффективный код так же плох.

EDIT: Исправил некоторые английские...

1
ответ дан 18 December 2019 в 06:34
поделиться

Для целых чисел == делает именно то, что вы ожидаете. Если они равны, они равны.

Для поплавков это отдельная история. Операции дают неточные результаты, и ошибки накапливаются. При работе с числами нужно быть немного расплывчатым. Я использую

if ( std::abs( a - b )
    < std::abs( a ) * ( std::numeric_limits<float_t>::epsilon() * error_margin ) )

, где float_t - это typedef; это дает мне максимальную точность (при условии, что error_margin вычислена правильно) и позволяет легко настроить другой тип.

Более того, некоторые значения с плавающей запятой не являются числами: есть бесконечность, минус бесконечность и, конечно же, не числа. == делает с ними забавные вещи. Бесконечность равна бесконечности, но не-число не равно не-числу.

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

Итак, если у вас нет более конкретного вопроса, я надеюсь, что он справится…

1
ответ дан 18 December 2019 в 06:34
поделиться

Сравнение <и> на самом деле не поможет вам с ошибками округления. Используйте решение, данное Марком Шеараром. Однако прямые сравнения на равенство для чисел с плавающей запятой не всегда плохи. Вы можете использовать их, если какое-то конкретное значение (например, 0,0 или 1,0) напрямую присвоено переменной, чтобы проверить, есть ли у переменной это значение. Только после расчетов ошибки округления портят проверки на равенство.

Обратите внимание, что сравнение значения NaN с чем-либо (также с другим NaN) с <,>, <=,> = или == возвращает false. ! = возвращает истину.

2
ответ дан 18 December 2019 в 06:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: