Jun. 18th, 2007

deniok: (Default)
RSDN лежит, я там, общаясь с[info]kurilka, сделал рукописный sin, перепощу сюда :-)

Ряд Тэйлора
f(x)=a0+a1*x+a2*x^2+...

Можно было просто вычислять коэффициенты и суммировать по ним. Однако мне не понравилось, что в каждом коэффициенте надо пересчитывать факториал заново - это повторяющиеся вычисления, которые к тому же выкинут нас из Int в Integer на втором десятке (это всё на самом деле копейки, но тем не менее). Чтобы избавиться от факториалов, я переразлагаю ряд Тэйлора в
f(x)=k(x)*(1+k1(x)*(1+k2(x)*(1+k3(x)*(1+k4(x)*(1+...)))))
где ki - функция от номера i и x.

Выражение
app k x n = (1+) . (k x n *)
в коде ниже как раз ФВП, которая выполняет 1+ki(x)*
Я мэпирую ее на список , получая список функций Float -> Float, которые потом сворачиваю фолдом по композиции. Ряд Тэйлора готов :)


-- Представляем ряд Тэйлора в виде f(x) = k_ini(x)*(1+k_n(x,1)*(1+k_n(x,2)(1+k_n(x,3)*(1+...)))))
-- где k_ini и k_n специфичны для конкретной функции 
taylor k_ini k_n x = k_ini x * foldr (.) id (map (app k_n x) [2..100]) 1
where app k x n = (1+) . (k x n *)

-- Для экспоненты exp x = 1+x/1!+x^2/2!+x^3/3!+... =
-- = 1*(1+x/1*(1+x/2*(1+x/3*(1+...))))
-- k_ini x = 1 
exp_my x = taylor (\x->1) k_n x
where k_n x n = x / fromIntegral (n-1)







-- Для синуса sin x = x/1!-x^3/3!+x^5/5!-... =
-- = x*(1-x^2/(2*3)*(1-x^2/(4*5)*(1-...)))
-- k_ini x = x --(id) 


sin_my x
= taylor id k_n x
where k_n x n = - x^2 / fromIntegral ((2*n-2)*(2*n-1))

-- Для косинуса cos x = 1-x^2/2!+x^4/4!-x^6/6!+... =
-- = 1*(1-x^2/(1*2)*(1-x^2/(3*4)*(1-...)))
-- k_ini x = 1

cos_my x = taylor (\x->1) k_n x
where k_n x n = - x^2 / fromIntegral ((2*n-3)*(2*n-2))

Profile

deniok: (Default)
deniok

February 2022

S M T W T F S
  12345
6789101112
13141516171819
20212223 242526
2728     

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 19th, 2025 03:16 pm
Powered by Dreamwidth Studios