На сайте habr.com/ru уже были похожие публикации осенью 2021 года:
Как посчитать синус быстрее всех
Не на Habr Как сделать быструю функцию для вычисления синуса? топик начат в 2003 году последний отклик в 2020 году.
Целью данной публикации попытка предложить способ расчета синуса и косинуса достаточно быстро для тех платформ, где отсутствуют эти функции (микроконтроллеры) или там где скорость расчета важнее точности.
Мне кажется, что выпуклые функции синус и косинус можно аппроксимировать не только рядом Тейлора ( многочленом вида a*x + b*x^3 +c*x^5 … ) , а обычной параболой поведенной через точки 1,2,3 как на рисунке.

Точки 1 и 2 базовые, размещаются с определенным задаваемым шагом. В скрипте Scilab это переменная step. Координаты точки 3 будем вычислять таким образом, чтобы в ней было максимальное отклонение синуса ( или косинуса ) от отрезка 1-2.
Ниже приведены скрипты на Scilab для расчета коэффициентов полинома второй степени на интервале [ 0 … pi /2] и графики отклонений для от функций синуса и косинуса .
Расчет коэффициентов для синуса на Scilab
/// синус function [a,b,c]= koef_parabola(x1,y1,x2,y2,x3,y3) /// расчет коэффициентов параболы по 3 точкам a1= y3 - ( x3*(y2-y1)+ x2*y1 -x1*y2 )/( x2-x1) a2= x3*( x3-x1-x2 ) + x1*x2 a= a1 /a2 b =( y2-y1)/( x2-x1) - a*( x1+x2) c=( x2*y1 - x1*y2) / (x2-x1) + a * x1*x2 endfunction kol_int =12 /// количество интервалов на отрезке 0 ... %pi/ 2 kol_funct =kol_int+1 step =%pi/ ( 2*kol_int) /// шаг point0_x =0:step:%pi/ 2 point0_sin = cos(point0_x) aa_sin =1:1:(kol_int) bb_sin =1:1:(kol_int) cc_sin =1:1:(kol_int) xx1=0 yy1=1 for ii=1:1:kol_int xx2=xx1+step yy2=cos(xx2) wsp1 =(yy2-yy1)/(xx2-xx1) /// наклон xx3=asin(-wsp1) /// координаты центральной точки yy3= sqrt( 1- wsp1^2) /// cos(xx3) [aa,bb,cc]=koef_parabola( xx1,yy1,xx2,yy2,xx3,yy3) aa_sin(ii)=aa bb_sin(ii)=bb cc_sin(ii)=cc xx1=xx2 yy1=yy2 end ///вывод шага и коэффициентов disp( step,aa_sin,bb_sin,cc_sin) xx1=0 xx2=step for ii=1:1:kol_int int01=[xx1:0.005:xx2] a1=aa_sin(ii) b1=bb_sin(ii) c1=cc_sin(ii) plot(int01, (cos(int01) - a1*int01^2 -b1*int01-c1 ) ) xx1=xx1+step xx2=xx2+step end
Пример отклонений для синуса
график отклонений полинома второй степени от синуса на интервале 0 … Пи/ 2 при разбиении на 8 интервалов ( размер интервала =Пи/ 16 примерно = 0.196 )
Расчет коэффициентов для косинуса на Scilab
function [a, b, c]=koef_parabola(x1, y1, x2, y2, x3, y3) /// расчет коэффициентов параболы по 3 точкам a1= y3 - ( x3*(y2-y1)+ x2*y1 -x1*y2 )/( x2-x1) a2= x3*( x3-x1-x2 ) + x1*x2 a= a1 /a2 b =( y2-y1)/( x2-x1) - a*( x1+x2) c=( x2*y1 - x1*y2) / (x2-x1) + a * x1*x2 endfunction kol_int =12 /// количество интервалов на отрезке 0 ... %pi/ 2 kol_funct =kol_int+1 step =%pi/ ( 2kol_int) /// шаг point0_x =0:step:%pi/ 2 point0_sin = cos(point0_x) aa_sin =1:1:(kol_int) bb_sin =1:1:(kol_int) cc_sin =1:1:(kol_int) xx1=0 yy1=1 for ii=1:1:kol_int xx2=xx1+step yy2=cos(xx2) wsp1 =(yy2-yy1)/(xx2-xx1) /// наклон xx3=asin(-wsp1) /// координаты центральной точки yy3= sqrt( 1- wsp1^2) /// cos(xx3) [aa,bb,cc]=koef_parabola( xx1,yy1,xx2,yy2,xx3,yy3) aa_sin(ii)=aa bb_sin(ii)=bb cc_sin(ii)=cc xx1=xx2 yy1=yy2 end ///вывод шага и коэффициентов disp( step,aa_sin,bb_sin,cc_sin) xx1=0 xx2=step for ii=1:1:kol_int int01=[xx1:0.005:xx2] a1=aa_sin(ii) b1=bb_sin(ii) c1=cc_sin(ii) plot(int01, (cos(int01) - a1*int01^2 -b1*int01-c1 ) ) xx1=xx1+step xx2=xx2+step end
Пример отклонений для косинуса
график отклонений полинома второй степени от синуса на интервале 0 … Пи/ 2 при разбиении на 12 интервалов

Синус таблица коэффициентов полинома степени 2 для 8 интервалов
( шаг Пи / 16 )

Я не привожу кода на каком либо языке или псевдокода, дабы не засорять публикацию, каждый желающий может подобрать себе коэффициенты полинома степени 2 для аппроксимации и написать свою функцию. По значению аргумента x вычисляем номер интервала, запоминаем коэффициенты и подставляем из в формулу полинома
ссылка на оригинал статьи https://habr.com/ru/post/654095/
Добавить комментарий