покрытие угла на вектор и обратно меняет угол?

Итак, у меня есть следующий угол (рад): 3.45575213
Теперь я конвертирую это через cos & грех к вектору (tDir равен нулю раньше):

tDir.x += cos(target->direction);
tDir.y += sin(target->direction);

теперь я конвертирую его обратно через:

float newDir = Wrap2PI(atan2(tDir.y, tDir.x));

Упаковка выглядит так:

inline float Wrap2PI(float u)
{
while(u < 0)
u += PI2;
while (u >= PI2)
u -= PI2;
return u;
}

ЧИСЛО ПИ:

const float PI = 3.14159265359f;
const float PI2 = PI*2.0f;

результат значительно отличается: 3.45575237

Эта разница действительно велика, когда этот расчет выполняется 120 раз в секунду, или, по крайней мере, кажется, что мои объекты вращаются по часовой стрелке, и это единственная неточность, которую мне удается найти в моем коде. Есть ли способ получить лучшие результаты?

РЕДАКТИРОВАТЬ: нашел проблему! Это была не неточность, вектор иногда был 0,0! Виноват!

0

Решение

Если вам нужна лучшая точность, вам нужно использовать как минимум doubleс не floats.

Заметим:

const float PI = 3.14159265359f;
printf("%0.15f\n", PI);

Выходное значение равно 3.141592741012573, которое показывает, что значение сохраняется только с точностью до 6 цифр после десятичной точки. Это фундаментальное ограничение float тип данных.

Если вы используете doubleвы будете лучше, и long doubles еще лучше. Но повторные применения трансцендентных функций в плавающей точке никогда не сработают в любом случае, поэтому вам, вероятно, следует избегать преобразования, за исключением случаев, когда это абсолютно необходимо. Придерживайтесь наиболее удобного представления для внутренних операций и конвертируйте только для ввода-вывода, например.

4

Другие решения

float дает вам точность 6-7 цифр. Рассмотреть возможность использования double,

И в любом случае, повторное применение тригонометрических функций рано или поздно приведет к некоторому расхождению.

2

С точки зрения численного анализа, я не нахожу странным, что опубликованная вами процедура приводит к ошибке 0,00000024. Тригонометрические функции в C / C ++ используют внутренние итерационные процедуры (например, метод Ньютона-Рафсона) для аппроксимации своих результатов.

Однако вы можете повысить свою точность, либо изменив float в double или же long double без каких-либо затрат производительности. Тем не менее, если точность является фактором № 1, вы можете использовать математическую библиотеку произвольной точности, например: GMP. Однако обратите внимание, что использование таких пакетов влияет на производительность (то есть скорость).

1