Название: Шутка QLineF::angleTo() Отправлено: Гурман от Июль 07, 2015, 22:20 Гоняю приложение в Релизе, и только сейчас заметил, что у меня кое-где не сработала оптимизация ортогональных маршрутов. Запускаю Креатор, в нём отладочную версию - а там всё работает, как надо. Недавно похожее было, но там с доступами к файлам библиотек и диагностикой были проблемы, но сейчас никаких библиотек нет и в помине, используется только QtCore. Проблему быстро обнаружил, она оказалась в функции вычисления угла между двумя линиями QLineF::angleTo(QLineF). В первой колонке таблицы значения, которые эта функция мне выдала при запуске отладочной версии, а во второй колонке - при запуске релиза:
Ну 3.5*10^-15 вместо 0, это ещё ладно, я этот момент заранее предусмотрел fuzzy-сравнением. Но вот разворот на 360 градусов (именно в этих случаях оптимизация не сработала), причём блин ровно - это уже издевательство какое-то... :D Название: Re: Шутка QLineF::angleTo() Отправлено: Fregloin от Июль 07, 2015, 23:19 что мешает сделать свою реализацию? лично я так и делал
Название: Re: Шутка QLineF::angleTo() Отправлено: Гурман от Июль 08, 2015, 00:09 Да ничего не мешает, только не нужна она. Ну добавил проверку ещё и на 360 градусов, тоже fuzzy на всякий случай, и проблема ушла. Просто как-то это было ну ооочень неожиданно, и нормальной логике не поддаётся. Особенно смачно это смотрится по сравнению с дебаггером, где тихо всё, шито-крыто... А тема тут - на всякий случай, для тех, кто дальше упрётся фейсом об тейбл в похожих ситуациях. Я быстро в Сети ничего такого не нашёл.
Название: Re: Шутка QLineF::angleTo() Отправлено: Авварон от Июль 09, 2015, 00:11 Зарепортьте багу с примером компилябельным. Я косяков не вижу, похоже оптимизатор шалит:
Код: qreal QLineF::angleTo(const QLineF &l) const Название: Re: Шутка QLineF::angleTo() Отправлено: Гурман от Июль 09, 2015, 00:22 Зарепортьте багу с примером компилябельным. Я косяков не вижу, похоже оптимизатор шалит: Код: delta < 0 ? delta + 360 : delta Вот. Если delta условно "-0", например -3.50414e-15, то будет ответ 360, а при таком же положительном значении - это значение, то есть, "+0". Зависит уже от вычисления angle() каждого отрезка. Фишка в том, что отрезки могут быть разнонаправленными и с четырьмя разными углами к горизонтали. angle() получается немного разным в разных случаях, это же вещественное двойной точности, с неизбежным "шумом" младших разрядов. Чтобы пример получить, надо потратить время на охоту за нужными положениями отрезков. Сейчас у меня его нет, может быть на выходных. Почему в отладчике всё ровно 0 - это другой вопрос... Это действительно похоже на баг. Название: Re: Шутка QLineF::angleTo() Отправлено: Авварон от Июль 09, 2015, 10:16 А, собственно бага-то вот она:
Код: - if (qFuzzyCompare(delta, qreal(360))) Название: Re: Шутка QLineF::angleTo() Отправлено: Авварон от Июль 09, 2015, 10:33 Можете привести корды линий, на к-ых бага происходит? Не могу подобрать:)
Название: Re: Шутка QLineF::angleTo() Отправлено: Авварон от Июль 09, 2015, 10:52 https://codereview.qt-project.org/#/c/121039/
Название: Re: Шутка QLineF::angleTo() Отправлено: Гурман от Июль 09, 2015, 12:36 А, собственно бага-то вот она: Код: - if (qFuzzyCompare(delta, qreal(360))) Не отвечает на вопрос - почему в отладчике работает правильно. Условная транслация не видна. Разве только если... отладочная библиотека собрана из другого исходника. :-\ Название: Re: Шутка QLineF::angleTo() Отправлено: Гурман от Июль 09, 2015, 12:37 Можете привести корды линий, на к-ых бага происходит? Не могу подобрать:) Чуть попозже, другие дела сейчас. Тоже ловить надо, где именно это вылазит. На сцене под сотню отрезков... Название: Re: Шутка QLineF::angleTo() Отправлено: Авварон от Июль 09, 2015, 13:04 Пока тестил, нашел еще одну "проблему" - qDebug печатает 359+1-0 (0 - очень малое) как 360, т.е. 359+1-0 < 360, но в консоли именно 360. Причем это "очень малое" ни фига не малое, на самом деле (оно больше чем e-5). То есть фаззи компар не всегда отрабатывает (см тест).
Название: Re: Шутка QLineF::angleTo() Отправлено: Igors от Июль 09, 2015, 16:27 Код: qreal QLineF::angleTo(const QLineF &l) const А, собственно бага-то вот она: Да, но это еще не все. В одну сторону округляем, в др нет. Поэтому возможна такая ситуацияКод: - if (qFuzzyCompare(delta, qreal(360))) Код Народная примета: если угол в градусах - реализация слабенькая. Fuzzy здесь вообще не к месту, вызывающему все равно самому надо округлять. Название: Re: Шутка QLineF::angleTo() Отправлено: Авварон от Июль 09, 2015, 23:08 Ошибки округления возможны, вы же не удивляетесь, получая разный результат в зависимости от того, сперва умножаете, а потом делите, или наоборот?
Upd: даже не так, эта проверка бесполезна, вы же не будете в клиентском коде писать Код: if (a.angleTo(b)) == 0) ... Код: if (qFuzzyIsNull(a.angleTo(b)))) ... Название: Re: Шутка QLineF::angleTo() Отправлено: Igors от Июль 10, 2015, 09:19 Вы напишете Из этого ничего хорошего не выйдет. Вообще в прикладной задаче есть свой epsilon, который может намного отличаться от используемого в Qt. Поэтому вероятно я напишу примерноКод: if (qFuzzyIsNull(a.angleTo(b)))) ... Код
Название: Re: Шутка QLineF::angleTo() Отправлено: Авварон от Июль 10, 2015, 13:47 Ну вот, уже qAbs забыли:)
|