Как работают тригонометрические функции?

102

Итак, в математике в старших классах и, возможно, в колледже нас учат, как использовать триггерные функции, что они делают и какие задачи решают. Но мне они всегда представлялись как черный ящик. Если вам нужен синус или косинус чего-либо, вы нажимаете кнопку sin или cos на своем калькуляторе, и все готово. Что нормально.

Мне интересно, как обычно реализуются тригонометрические функции.

Юрский_C
источник
Вы не знаете, что такое триггерные функции или как они реализованы?
Кайл Кронин
15
Я знаю, что это такое. Я знаю, что они делают. Я знаю, как определить, что мне нужно для какой цели. Я могу рассказать вам все о соотношении углов и расстояний. То, что я искал, было больше похоже на ответ Джона Д. Кука. И все, кто упомянул настоящие алгоритмы
Jurassic_C
Это хороший вопрос. Например, синус, косинус и тангенс являются трансцендентными функциями, и их сложно решить ... С другой стороны, их можно определить с помощью простого разложения в ряд Тейлора, которое даст вам правильный ответ с любой конечной степенью точности обязательный.
Alex

Ответы:

144

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

После того, как вы уменьшите аргумент, большинство микросхем используют алгоритм CORDIC для вычисления синусов и косинусов. Вы можете слышать, как люди говорят, что компьютеры используют серию Тейлора. Звучит разумно, но это неправда. Алгоритмы CORDIC намного лучше подходят для эффективной аппаратной реализации. ( Программное обеспечение библиотеки могут использовать серию Тейлора, скажем, на оборудовании, которое не поддерживает триггерные функции.) Может потребоваться некоторая дополнительная обработка с использованием алгоритма CORDIC для получения достаточно хороших ответов, но затем для повышения точности выполняется что-то еще.

В вышесказанное есть некоторые уточнения. Например, для очень малых углов theta (в радианах) sin (theta) = theta для всей имеющейся точности, поэтому более эффективно просто вернуть theta, чем использовать какой-либо другой алгоритм. Таким образом, на практике существует много логики для особых случаев, чтобы выжать из них всю возможную производительность и точность. Для чипов с меньшими рынками может потребоваться меньше усилий по оптимизации.

Джон Д. Кук
источник
4
Отличный ответ - хотя CORDIC на самом деле не нуждается в уменьшении дальности как таковом (фактически, это, по сути, сам по себе алгоритм уменьшения дальности); он отлично работает для углов между -pi / 2 и + pi / 2, поэтому вам просто нужно выполнить поворот вектора на 180 градусов для углов вне этого диапазона.
Джейсон С.
3
Реализации, использующие полиномиальное приближение, часто могут использовать ряды Тейлора, но обычно они должны использовать коэффициенты, которые были определены с помощью алгоритма Ремеза. lolengine.net/blog/2011/12/21/better-function-approximations
Паскаль Куок
1
Обратите внимание, что таблица значений, используемая CORDIC, должна быть предварительно рассчитана. Итак, Тейлор все еще может использоваться «во время компиляции».
Rhubbarb
2
Кажется, что этот ответ противоречит принятому с высоким рейтингом ответу на этот аналогичный вопрос: stackoverflow.com/questions/2284860/… . В этом ответе говорится, что функция sin () в основном реализована на аппаратном уровне, а другая - на C.
Перри
48

edit: Джек Гэнссл имеет достойное обсуждение в своей книге по встроенным системам "The Firmware Handbook" .

К вашему сведению: если у вас есть ограничения по точности и производительности, ряд Тейлора не следует использовать для аппроксимации функций в численных целях. (Сохраните их для своих курсов по исчислению.) Они используют аналитичность функции в одной точке , например тот факт, что все ее производные существуют в этой точке. Они не обязательно сходятся в интересующем интервале. Часто они плохо справляются с распределением точности аппроксимации функции, чтобы быть «идеальными» прямо возле точки оценки; ошибка обычно увеличивается по мере удаления от нее. И если у вас есть функция с любой непрерывной производной (например, прямоугольные волны, треугольные волны и их интегралы), ряд Тейлора даст вам неправильный ответ.

Лучшее «простое» решение при использовании полинома максимальной степени N для аппроксимации заданной функции f (x) на интервале x0 <x <x1 - это приближение Чебышева ; см. Числовые рецепты для хорошей дискуссии. Обратите внимание, что Tj (x) и Tk (x) в статье Wolfram, которую я связал, использовали cos и обратный косинус, это многочлены, и на практике вы используете рекуррентную формулу для получения коэффициентов. Опять же, см. Числовые рецепты.

edit: В Википедии есть неплохая статья по теории приближений . Один из цитируемых ими источников (Харт, «Компьютерное приближение») больше не издается (а старые копии, как правило, дороги), но в нем подробно рассказывается о подобных вещах. (Джек Гэнссл упоминает об этом в 39 выпуске своего информационного бюллетеня The Embedded Muse .)

редактировать 2: Вот несколько ощутимых показателей ошибок (см. ниже) для Тейлора и Чебышева для sin (x). Некоторые важные моменты, на которые следует обратить внимание:

  1. что максимальная ошибка приближения ряда Тейлора в заданном диапазоне намного больше, чем максимальная ошибка приближения Чебышева той же степени. (Примерно для той же ошибки вы можете обойтись одним термином меньше с Чебышевым, что означает более высокую производительность)
  2. Снижение дальности - огромная победа. Это связано с тем, что вклад многочленов более высокого порядка уменьшается, когда интервал приближения меньше.
  3. Если вы не можете обойтись с уменьшением диапазона, ваши коэффициенты необходимо сохранить с большей точностью.

Не поймите меня неправильно: серия Тейлора будет работать правильно для синуса / косинуса (с разумной точностью для диапазона от -pi / 2 до + pi / 2; технически, имея достаточное количество терминов, вы можете достичь любой желаемой точности для всех реальных входов, но попробуйте вычислить cos (100) с использованием ряда Тейлора, и вы не сможете этого сделать, если не используете арифметику произвольной точности). Если бы я застрял на необитаемом острове с ненаучным калькулятором и мне нужно было вычислить синус и косинус, я бы, вероятно, использовал ряд Тейлора, поскольку коэффициенты легко запомнить. Но в реальном мире приложения для того , чтобы написать свой собственный грех () или соз () функция достаточно редкие , что вы бы лучше с помощью эффективной реализации для достижения требуемой точности - что ряд Тейлора не .

Диапазон = от -pi / 2 до + pi / 2, степень 5 (3 члена)

  • Тейлор: макс ошибка вокруг 4.5e-3, F (X) = хх 3 /6 + х 5 /120
  • Чебышев: максимальная ошибка около 7e-5, f (x) = 0,9996949x-0,1656700x 3 + 0,0075134x 5

Диапазон = от -pi / 2 до + pi / 2, степень 7 (4 члена)

  • Тейлор: макс ошибка вокруг 1.5e-4, F (X) = хх 3 /6 + х 5 /120-х 7 /5040
  • Чебышев: максимальная ошибка около 6e-7, f (x) = 0,99999660x-0,16664824x 3 + 0,00830629x 5 -0,00018363x 7

Диапазон = от -pi / 4 до + pi / 4, степень 3 (2 члена)

  • Тейлор: макс ошибка вокруг 2.5E-3, F (X) = хх 3 /6
  • Чебышев: максимальная ошибка около 1,5e-4, f (x) = 0,999x-0,1603x 3

Диапазон = от -pi / 4 до + pi / 4, степень 5 (3 члена)

  • Тейлор: макс ошибка вокруг 3.5E-5, F (X) = хх 3 /6 + х 5
  • Чебышев: максимальная ошибка около 6e-7, f (x) = 0,999995x-0,1666016x 3 + 0,0081215x 5

Диапазон = от -pi / 4 до + pi / 4, степень 7 (4 члена)

  • Тейлор: макс ошибка вокруг ого-7, F (X) = хе 3 /6 + х 5 /120-х 7 /5040
  • Чебышев: максимальная ошибка около 1,2e-9, f (x) = 0,999999986x-0,166666367x 3 + 0,008331584x 5 -0,000194621x 7
Джейсон С
источник
2
Этот комментарий неверен. Для каждого приближения есть время и место. Если вы не знаете достаточно анализа, чтобы определить область сходимости для ЛЮБОГО приближения ряда, вам НЕ следует его использовать. Это касается серий Тейлор, Чебышев, Паде и т. Д. Серии Тейлора часто достаточно хороши.
kquinn
4
: shrug: Не знаю, как вы, но мне никогда не было интересно оценивать функцию в небольшом районе вокруг одной точки. Даже быстрая подгонка методом наименьших квадратов к интервалу чертовски легко. Любой, кто использует серию Тейлора, просто не понимает сути.
Джейсон С.
1
@kquinn: область сходимости для чебышевских приближений не является полезным понятием, поскольку интервал, на котором они вычисляются, является явным входом в процесс.
Джейсон С.
2
Голосование за, потому что ответчик знал, что Харт существует. : smile: Харт - классический образец здесь, даже если его было трудно найти, когда я купил копию (в печати) 25 лет назад. Это стоит каждого пенни. Уменьшение дальности там, где это возможно, в сочетании с подходящей аппроксимацией, будь то ряд Паде, Чебычева или даже ряды Тейлора, если это необходимо, является хорошим подходом. Однако приближения Паде или Чебычева обычно лучше, чем ряды Тейлора.
3
??? Чем это отличается? Ряд Тейлора до 17-й степени для вычисления sin (x) от -2pi до + 2pi, вероятно, может быть побежден Чебышевым с полиномом 7-й или 9-й степени. У меня не возникло бы проблем с утверждением: «Если у вас не хватает времени на вырубку деревьев, вам не следует пользоваться ручной пилой. Используйте бензопилу». Возможно, мне стоит перефразировать с «не следует» на что-то вроде «Я бы не рекомендовал использовать серию Тейлора». Конечно, в некоторых случаях вы можете использовать серию Тейлора, но ваша точность и производительность будут проблематичными. Под производительностью я подразумеваю время выполнения ЦП.
Jason S
14

Я считаю, что они рассчитаны с использованием серии Тейлора или CORDIC . Некоторые приложения, интенсивно использующие триггерные функции (игры, графика), при запуске создают таблицы триггеров, чтобы они могли просто искать значения, а не пересчитывать их снова и снова.

Джон Гэллоуэй
источник
6

Проверьте статью Википедии на функцию аккуратных. Хорошее место, где можно узнать, как их реализовать в коде, - это числовые рецепты .

Я не особо разбираюсь в математике, но мое понимание того, откуда «берутся» sin, cos и tan, заключается в том, что они в некотором смысле наблюдаются, когда вы работаете с прямоугольными треугольниками. Если вы измеряете длины сторон группы разных прямоугольных треугольников и наносите точки на график, вы можете получить из этого sin, cos и tan. Как указывает Харпер Шелби, функции просто определяются как свойства прямоугольных треугольников.

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

Параппа
источник
1

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

Метод CORDIC быстрее, поскольку он реализован на оборудовании, но в основном он используется для встроенных систем, а не для стандартных компьютеров.

Джошуа Ховард
источник
0

Я хотел бы расширить ответ, предоставленный @Jason S. Используя метод подразделения домена, аналогичный описанному @Jason S, и используя приближения серии Маклорена, среднее (2-3) X ускорение по сравнению с tan (), sin () , cos (), atan (), asin () и acos (), встроенные в компилятор gcc, с оптимизацией -O3. Лучшие аппроксимирующие функции ряда Маклорена, описанные ниже, достигли точности двойной точности.

Для функций tan (), sin () и cos () и для простоты перекрывающаяся область от 0 до 2pi + pi / 80 была разделена на 81 равный интервал с «точками привязки» в pi / 80, 3pi / 80, ..., 161 дюйм / 80. Тогда тангенс (), SIN () и COS () эти 81 опорных точек были оценены и сохранен. С помощью триггерных идентификаторов для каждой триггерной функции была разработана одна функция серии Маклорена. Любой угол между ± бесконечностью может быть представлен триггерной аппроксимирующей функции, поскольку функции сначала переводят входной угол в область от 0 до 2pi. Эти накладные расходы на перевод включены в накладные расходы аппроксимации.

Аналогичные методы были разработаны для функций atan (), asin () и acos (), где перекрывающийся домен от -1,0 до 1,1 был разделен на 21 равный интервал с точками привязки в -19/20, -17/20, .. ., 19/20, 21/20. Тогда только atan () из этих 21 точек привязки был сохранен. Опять же, с помощью тождеств обратных триггеров, для функции atan () была разработана одна функция ряда Маклорена. Затем результаты функции atan () использовались для аппроксимации asin () и acos ().

Поскольку все аппроксимирующие функции обратного триггера основаны на аппроксимирующей функции atan (), разрешено любое входное значение аргумента двойной точности. Однако аргумент, входящий в аппроксимирующие функции asin () и acos (), усекается до области ± 1, потому что любое значение вне его не имеет смысла.

Чтобы проверить аппроксимирующие функции, необходимо было оценить миллиард случайных оценок функций (то есть оптимизирующему компилятору -O3 не разрешалось обходить оценку чего-либо, потому что некоторые вычисленные результаты не использовались). Чтобы удалить смещение оценки миллиарда случайных чисел и обработки результатов, сначала рассчитывалась стоимость запуска без оценки какой-либо триггерной или обратной триггерной функции. Затем это смещение вычиталось из каждого теста, чтобы получить более репрезентативное приближение фактического времени оценки функции.

Таблица 2. Время, затраченное в секундах на выполнение указанной функции или функций миллиард раз. Оценки получаются путем вычитания временных затрат на оценку одного миллиарда случайных чисел, показанных в первой строке таблицы 1, из остальных строк таблицы 1.

Время, проведенное в загар (): 18.0515 18.2545

Время нахождения в TAN3 (): 5.93853 6.02349

Время, проведенное в TAN4 (): 6.72216 6.99134

Время, проведенное в sin () и cos (): 19,4052 19,4311

Время, проведенное в SINCOS3 (): 7.85564 7.92844

Время, проведенное в SINCOS4 (): 9,36672 9,57946

Время нахождения в атане (): 15.7160 15.6599

Время нахождения в ATAN1 (): 6.47800 6.55230

Время, проведенное в ATAN2 (): 7.26730 7.24885

Время нахождения в ATAN3 (): 8.15299 8.21284

Время, проведенное в asin () и acos (): 36,8833 36,9496

Время, проведенное в ASINCOS1 (): 10,1655 9,78479

Время, проведенное в ASINCOS2 (): 10,6236 10,6000

Время, проведенное в ASINCOS3 (): 12.8430 12.0707

(В целях экономии места таблица 1 не показана.) Таблица 2 показывает результаты двух отдельных прогонов миллиарда оценок каждой аппроксимирующей функции. Первый столбец - это первый прогон, а второй столбец - второй прогон. Цифры «1», «2», «3» или «4» в именах функций указывают количество терминов, используемых в функции ряда Маклорена для оценки конкретного триггерного или обратного триггерного приближения. SINCOS # () означает, что sin и cos были вычислены одновременно. Аналогичным образом, ASINCOS # () означает, что asin и acos оценивались одновременно. Одновременная оценка обеих величин не требует дополнительных затрат.

Результаты показывают, что увеличение количества условий немного увеличивает время выполнения, как и следовало ожидать. Даже наименьшее количество членов дает точность около 12-14 цифр везде, за исключением приближения tan (), где его значение приближается к ± бесконечности. Можно было бы ожидать, что даже у функции tan () будут проблемы.

Аналогичные результаты были получены на ноутбуке MacBook Pro высокого класса в Unix и на настольном компьютере высокого класса в Linux.

Роджер Вехаге
источник
-5

Если вы просите более физического объяснения sin, cos и tan, подумайте, как они соотносятся с прямоугольными треугольниками. Фактическое числовое значение cos (лямбда) можно найти, сформировав прямоугольный треугольник с одним из углов, являющимся лямбдой, и разделив длину стороны треугольника, примыкающей к лямбде, на длину гипотенузы. Точно так же для sin используйте противоположную сторону, разделенную гипотенузой. Для касательной используйте противоположную сторону, разделенную на соседнюю. Классический мемоник, который нужно запомнить, - это SOHCAHTOA (произносится как сокатоа).

JeffD
источник