Итак, у меня есть следующий угол (рад): 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! Виноват!
Если вам нужна лучшая точность, вам нужно использовать как минимум double
с не float
s.
Заметим:
const float PI = 3.14159265359f;
printf("%0.15f\n", PI);
Выходное значение равно 3.141592741012573, которое показывает, что значение сохраняется только с точностью до 6 цифр после десятичной точки. Это фундаментальное ограничение float
тип данных.
Если вы используете double
вы будете лучше, и long doubles
еще лучше. Но повторные применения трансцендентных функций в плавающей точке никогда не сработают в любом случае, поэтому вам, вероятно, следует избегать преобразования, за исключением случаев, когда это абсолютно необходимо. Придерживайтесь наиболее удобного представления для внутренних операций и конвертируйте только для ввода-вывода, например.
float
дает вам точность 6-7 цифр. Рассмотреть возможность использования double
,
И в любом случае, повторное применение тригонометрических функций рано или поздно приведет к некоторому расхождению.
С точки зрения численного анализа, я не нахожу странным, что опубликованная вами процедура приводит к ошибке 0,00000024. Тригонометрические функции в C / C ++ используют внутренние итерационные процедуры (например, метод Ньютона-Рафсона) для аппроксимации своих результатов.
Однако вы можете повысить свою точность, либо изменив float
в double
или же long double
без каких-либо затрат производительности. Тем не менее, если точность является фактором № 1, вы можете использовать математическую библиотеку произвольной точности, например: GMP. Однако обратите внимание, что использование таких пакетов влияет на производительность (то есть скорость).