Позволяет нам прояснить некоторые причинно-следственные связи и копать глубже.
Неправильная формула для области
Площадь составляет 1/2 от формулы ОП, но это не делает различий при сравнении с 0.0.
// area=(Ax* (By-Cy) + Bx* (Cy-Ay) + Cx* (Ay-By));
area=(Ax* (By-Cy) + Bx* (Cy-Ay) + Cx* (Ay-By))/2;
Неточность
«поскольку двойные и плавающие числа очень неточны», само по себе неточно. Все конечные значения FP точны , как целые числа. Именно при сравнении их операций с математическим делением они получают неправильное число «неточно». Как и целочисленное деление, деление FP и другие базовые математические операции FP, они определяются иначе, чем математические операции. 7/3 и 7.0 / 3.0 оба не приводят к математическому 2 1 / 3 , но имеют другое значение. Когда C использует математическую модель IEEE, этот «коэффициент» не является приблизительным, но точным.
Сравнивая сколько?
«сравнить 2 двойки» вводит в заблуждение, так как эффективно это сложное сравнение 6 double
, которое должен выполнить код.
Обзор формулы теста
Ax* (By-Cy) + Bx* (Cy-Ay) + Cx* (Ay-By)
с double
операндами будет вести себя без округления, пока подэтапы не округляются. В general это невозможно. Обходные пути
- Используйте более высокую точность
Выполните тест, используя long double
. Это не устраняет проблему, а только делает ее меньше / менее вероятной. Примечание long double
необязательно иметь более высокую точность.
- Используйте какой-нибудь эпсилон
Наивный подход берет результат | вычисленная площадь | и сравнивается с эпсилон . Абсолютные области ниже, которые считаются "нулем". Это не очень хорошо масштабируется, так как epsilon действительно зависит от величины операндов относительно области. Необходим относительный эпсилон. Предложить fmax(|ax|,|bx|,|cx|) * fmax(|ay|,|by|,|cy|) * DBL_EPSILON
. Это только приближение первого порядка.
- Искать смену знака
Формула площади - это область со знаком . Эффективно изменяя порядок a, b, c инвертирует знак области. Если небольшое возмущение любого из 8 операндов на operand_new=operand*(1 +/- DBL_EPSILON)
приведет к изменению знака области, площадь можно оценить как "достаточно близкую к нулю".
- Переупорядочить формулу.
Это вычитание значений удаленных значений, которые убивают точность. Обмен x
s на y
s может помочь во внутренних вычитаниях термина. Повторный заказ вычитания 3 продуктов может помочь.
Более качественный повторный заказ может быть выполнен в форме формирования 6 продуктов: Ax By, -Ax Cy, Bx Cy, -Bx Ay, Cx Ay, -Cx Затем суммировать их.
Оба из этих преимуществ используют алгоритм суммирования Кахана SO , возможно, с использованием fma()
.
Для меня я бы исследовал # 4b или # 3. Если бы ОП опубликовал Минимальный, завершенный и проверяемый пример , данные образца и ожидаемые результаты образца, можно было бы получить истинный код. Не имея этого, рассмотрим эти исходные идеи для нечеткой задачи.