Повторная настройка уравнения с плавающей точкой
Я хотел бы знать, есть ли способ повысить точность расчета наклона. (Это появилось несколько месяцев назад здесь).
Кажется, изменив:
float get_slope(float dXa, float dXb, float dYa, float dYb) {
return (dXa - dXb)/(dYa - dYb);
}
в
float get_slope(float dXa, float dXb, float dYa, float dYb) {
return dXa/(dYa - dYb) - dXb/(dYa - dYb);
}
может быть улучшение. Предложения?
Изменить: это точность, я после, а не эффективность.
3 ответа
Примените их, чтобы удвоить внутри функции.
Очевидно, что вы столкнетесь с неприятностями, когда знаменатель приблизится к нулю. Ваш склон будет приближаться к бесконечности. Так что многое зависит от того, что вы хотите сделать на склоне. Иногда, если вы знаете, что ваша дельта y будет близка к нулю, вы можете вычислить обратную величину наклона и использовать ее вместо этого. Вы даже можете определить, какая из них меньше - абсолютное значение deltax или deltay и вернуть наклон или 1/ наклон. Также посмотрите на atan2().
Если вы знаете, что входные данные представлены в десятичном формате, а также хотите, чтобы выходные данные были в десятичном формате, вы можете преодолеть потерю точности, присущую преобразованию чисел с плавающей запятой в двоичную и обратно, выполнив все вычисления с использованием десятичной библиотеки. Я помню, как мне было приятно, когда я использовал Atari BASIC для десятичных вычислений, поскольку он использовал режим BCD 6502.
Если вы не возражаете сжечь некоторые дополнительные циклы, вы можете получить большую точность, выполняя цикл.
Рассчитайте наклон отрезка между A и B.
Вычислить наклон отрезка между {(Xa - (Xa -Xb)), (Ya - (Ya -Yb)} и {(Xb + (Xa-Xb)), (Yb + (Ya - Yb))}... В основном A - наклон и B + наклон.
Затем сравните полученные склоны. Если разница слишком велика (выберите желаемый порог), продолжайте движение и в конце усредните все уклоны.
Это может помочь сгладить аномалии, вызванные арифметикой с плавающей запятой, для очень маленьких склонов.
Я думаю, что у вас есть опечатка. Вы, наверное, имеете в виду
return dXa/(dYa - dYb) - dXb/(dYa - dYb);
Я бы сказал, что первая форма, которую вы дали, имеет более высокую точность. Если dXa и dXb близки и велики, то перед вычитанием вы потеряете точность в двух делениях.