На сайте 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 вычисляем номер интервала, запоминаем коэффициенты и подставляем из в формулу полинома