Найти в Дзене

Ещё один способ сравнения вещественных чисел

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

Расскажу на примере языка РНР, хотя это справедливо для любых языков. Просто РНР мне волей-неволей приходится использовать, поэтому я его по мере возможности изучаю и делюсь некоторым познаниями. Правда, в РНР и других подобных языках, где не надо указывать тип переменных, указанная проблема может встречаться редко, поскольку по умолчанию используется самый большой тип данных с наивысшей точностью. Но в этом и засада, потому что может случиться ситуация, когда вы “1000 раз так делали”, а на 1001 что-то пойдёт не так.

Например, такой код на РНР:

$x = 10.0;
$y = $x / 3.0;
if ($x == ($y * 3.0))
echo $x, ' = ', $y * 3.0;
else
echo $x, ' НЕ РАВНО ', $y * 3.0;

может вывести ожидаемое значение “10 = 10”, в отличие от примера на Паскале, ссылка на который дана выше. Однако расслабляться не стоит. Потому что в другом похожем случае всё может быть хуже. Например, даже современный РНР мы можем заставить ошибиться, если используем очень большое число:

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

-2

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

  • Каждое из сравниваемых чисел мы умножаем на 10
  • Результат преобразуем в целые числа с помощью функции intval
  • Сравниваем целые числа

Конечно, при преобразовании теряется и точность. Но всё же лучше потерять точность, чем получить труднонаходимые глюки в программе. Для повышения точности можно выполнять умножение не на 10, а, например, на 100 или 1000. Но при этом надо помнить, что так можно выйти из допустимого диапазона, и это тоже приведёт к ошибке сравнения.

На этом всё. Подписывайтесь на канал, чтобы ничего не пропустить.