Комментарии 25
А нужно как-то так:
bool is_not_equal(double a, double b) {
return std::fabs(a - b) > std::numeric_limits<double>::epsilon();
}
Можно написать ещё проще:
//current = round(current * 1000.0) / 1000.0;
//cout << current << endl; //<-- COMMENT BACK IN TO "FIX" BUG
} while (fabs(current - last) >= 1e-3);
А round
не нужен. Это источник потенциальных ошибок. Например, если результат будет последовательно меняться: 1.0005 + eps, 1.0005 — eps,…, тогда даже если eps будет очень мало, мы никогда не остановимся.
Как минимум, эпсилон ещё нужно масштабировать на величину наибольшего значения, иначе на больших числах такое сравнение мало поможет.
std::fabs(a - b) <= std::numeric_limits<T>::epsilon() * std::max(std::abs(a), std::abs(b)) * units_in_the_last_place;
для применения epsilon нужно сначала отделить порядок от мантиссы, иначе у вас 1E-30 будет равен 1E-20
Продолжая квантовую тему, предлагаю ввести Эверетт-баг: когда код выполняется в какой-то "параллельной Вселенной" и его результаты абсолютно не соотносятся с исходниками. Обычно происходят по причине неправильного билда, либо ввиду внутренних багов используемых библиотек.
Ха! Вот только за последние три месяца (специфично для Java):
- Пустой catch. Вредитель, писавший бизнес-логику верхнего уровня, замолчал исключение и поставил try с пустым catch. В итоге мы думали, что сбой ниже — в протоколе передачи: данные-то на экране показывались совсем левые, а исключение "типа" не выбрасывалось.
- Невозможное поведение на сертификационном вокрбенче. Тестовая группа клиента отправляет нам багрепорты, которые уже давно были пофикшены и на тестах не возникали. Две недели компостировали нам мозги: делаем в коде различные "подпорки" для гипотетических (и невозможных) случаев, добавляем больше логов. В итоге требую доступ к сертификационной машине и вижу — о чудо — определена переменная CLASSPATH и в нее добавлены старые .jar-ы из другой директории...
- Пустой-не пустой список. Функция фильтровала значения в списке, но на выход выдавала всегда пустой. Причем на все 100% верная и локально все тесты проходит. А на сервере не выдает. После разделывания кода оказался баг в библиотеке ORM, который выдавал "бажной" IndirectList: https://bugs.eclipse.org/bugs/show_bug.cgi?id=433075
- В задеплоенном приложении тупо не работали периодические процессы, а ошибки в логах не было. В результате головной боли обнаружилось, что клиент использовал кривой sftp, который почему-то обрезал концовку файла. А возникавший NoClassDefFoundError не перехватывался catch(Exception e) и поэтому в лог не выводился.
Да и ошибки в компиляторах никто не отменял. Уже 2 раза с таким сталкивался.
Не запускалась стиральная машинка: вместо стирки гудит и выключается. Через неделю работает. А потом нет. Нет стабильности.
Оказалось, в нее вода не поступает. Или поступает — как получится. Тройник между холодной водой для раковины и стиральной машинкой был сделан на основе крана (с крутящейся ручкой), и вода поступает в обе системы только в некоторых положениях крана.
Вот вам костыль в сантехнике.
Буквально втыкаешь немного логгирования — все, либо ошибки нет, либо она проявляется совсем по-другому. И делай что хошь.
О-о-о, было же ещё круче! 5" дискеты. Был 40-дорожечный дисковод, поставили 80-дорожечные. Но у клиентов (за полярным кругом, между прочим), был 40-дорожечный, так что я форматировал под 40 дорожек. И — не работает. То есть там, у них — не работает. У меня — работает. Дискету возят самолётом, программа запускается именно с неё, наличие ложной копии на харде исключено — не было никаких хардов. Привозили, я записывал очередную версию, быстро на следующий самолёт, и — туда. Не работает :-)
… оказалось, что, поскольку «мой» дисковод был 80-дорожечным, в режиме 40 дорожек он писал только на половину ширины дорожки. И у пользователей считывалась старая версия, записанная, ещё когда у меня стоял 40-дорожечный дисковод. Ну, и не работала с новыми данными, ессно.
Разрешилось только, когда я, во-первых, слетал туда в командировку, во-вторых, личную дискету пустил в дело (тогда это было и дорого и дефицитно) — всё заработало сразу. И появилась возможность не спеша анализировать.
if (a!=b)
эквивалентно
if( true)
по определению.
Я такие вещи пишу только
if (abs(a-b)<1e-x)
где x — целое больше нуля
Что такое гейзенбаг: история термина и примеры