2016-01-23 3 views
0

К сожалению, я начинающий программист, но относительно опытный математик.Плавно замкнутые периодические тригонометрические функции

Я хотел попасть в развивающие игры, и я думаю, что я почти освоил основную математику линейных алгебр за некоторыми вещами вроде OpenGL. К сожалению, еще нет технических ноу-хау для графического моделирования.

В качестве элементарного упражнения я хотел попробовать и моделировать непрерывное движение частицы по круговой траектории. Я использовал простую параметризацию

double t=0; 
double x = cos(t), y = sin(t); 

Я знаю, что двойной имеет диапазон 1.7E +/- 308 в соответствии с Microsoft. Тогда мой вопрос будет: «Как я могу обеспечить гладкую непрерывную кольцевую петлю частицы?» Проблема, которая, как я думал, может случиться, заключается в том, что если бы программа работала достаточно долго, так как t становилось все больше и больше, мы достигли точки, где t сбрасывается до самого низкого значения и может вызвать «прыжок» в положение частицы.

Я подумал об этом, и я подумал, нужно ли создавать сопоставление для t из [1.7E-308, 1.7E + 308) → [0,2π). Помогло бы это предотвратить любую позицию «прыжки»? Или есть проблема в этом, что я не смотрю? Мой план состоял бы в том, чтобы увеличить t по заранее определенному курсу, который я еще не определил. Но я вижу скорость, с которой увеличивается t, определяет, как быстро меняются координаты x и.

ответ

1

Вы слишком беспокоитесь. Или, по крайней мере, о неправильном. Солнце превратится в красного гиганта и проглотит землю, задолго до того, как вы превысите максимум в два раза, добавив небольшие приращения.

Несколько более серьезная проблема заключается в том, что абсолютная точность t уменьшается по мере увеличения ее величины. Это основано на том, что точность двойника относительно ее величины. Даже это займет очень много времени, прежде чем это станет реальной проблемой, но это происходит задолго до того, как t превысит двойной диапазон.

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

Все, что сказано, избегая любой из этих проблем, столь же удаленных, как они могут быть на самом деле, настолько просто, что вы можете также позаботиться об этом. Вы просто уменьшить значение t как только она превышает 2 * пи после увеличения его:

t += tInc; 
if (t > 2.0 * M_PI) 
{ 
    t -= 2.0 * M_PI; 
} 

При этом, значение всегда будет оставаться в пределах от 0 до 2 * пи.

BTW: Это должно быть очень редкой, что вам нужна двойная точность для всего, что связано с графикой. Использование переменных и констант типа float должно быть достаточным, если у вас нет очень необычного варианта использования.Графическая библиотека, которую вы будете использовать, как правило, будет работать в точности float, поэтому использование double в вашем собственном коде просто будет использовать дополнительную память и приведет к большому количеству преобразований типов.

+0

Я думаю, что использование M_PI для ручного сокращения аргументов приведет к все возрастающему фазовому сдвигу в вычисленных значениях синуса и косинуса по сравнению с 'sincos (i * angle_increment, & s, & c)', поскольку M_PI просто аппроксимирует математическое π, но в зависимости от варианта использования, это может не иметь значения. Неразрешенные реализации 'sin(), cos(), sincos()' будут использовать достаточно точное внутреннее приближение к π, чтобы избежать проблемы фазового сдвига. – njuffa

+0

@njuffa Что вы сравниваете? Независимо от того, как вы справляетесь с этим, у вас будут ошибки из-за ограниченной точности с плавающей запятой. Как я объяснил, значение 't' само по себе потеряет точность, если оно станет больше. В какой-то момент, когда точность становится больше, чем приращение, она перестанет расти. Казалось бы, это гораздо более серьезная проблема. –

+0

Я полностью согласен с тем, что гранулярность представления с плавающей запятой увеличивается с ростом величины аргумента, вызывающего проблему в конечном итоге. Так как искатель использует 'double', это займет много углов, прежде чем это превратится в значительную проблему, в частности, если умножение используется для подсчета приращений угла. Моя точка зрения состоит в том, что уменьшение ручного аргумента методом «M_PI» в соответствии с предложенным выше способом обычно не предпочтительнее использования правильно реализованных тригонометрических функций из стандартной математической библиотеки C/C +, поскольку они включают более точное сокращение внутренних аргументов. – njuffa

Смежные вопросы