Есть несколько возможных решений для этого. Но один подход будет следующим:
Для определения a
и b
в функции линии тренда y = a*e^(b*x)
существуют решения, использующие собственные функции Calc
(LINEST
, EXP
, LN
).
Таким образом, мы можем y = a*e^(b*x)+c
принять за y-c= a*e^(b*x)
, и поэтому, если мы знаем c
, решение для y = a*e^(b*x)
также может быть принято. Как узнать с? Один подход описан в Пример экспоненциальной кривой . Там аппроксимация b, a, а затем c.
У меня есть основная часть кода delphi из Пример экспоненциальной кривой: список источников переведен в StarBasic
для Calc
. Часть тонкой настройки c
до сих пор не переведена. To-Do для вас, как профессиональных программистов и энтузиастов.
Пример:
Данные:
x y
0 0.767838478
1 0.702426493
2 0.733858228
3 0.703275979
4 0.651456058
5 0.62427187
6 0.742353261
7 0.646359026
8 0.695630431
9 0.659101665
10 0.598786652
11 0.592840135
12 0.59199059
Формулы:
B17
: =EXP(INDEX(LINEST(LN($B$2:$B$14),$A$2:$A$14),1,2))
C17
: =INDEX(LINEST(LN($B$2:$B$14),$A$2:$A$14),1,1)
y = a*e^(b*x)
также является функцией, используемой для расчета линии тренда графика.
B19
: =INDEX(TRENDEXPPLUSC($B$2:$B$14,$A$2:$A$14),1,1)
C19
: =INDEX(TRENDEXPPLUSC($B$2:$B$14,$A$2:$A$14),1,2)
D19
: =INDEX(TRENDEXPPLUSC($B$2:$B$14,$A$2:$A$14),1,3)
Код:
function trendExpPlusC(rangey as variant, rangex as variant) as variant
'get values from ranges
redim x(ubound(rangex)-1) as double
redim y(ubound(rangex)-1) as double
for i = lbound(x) to ubound(x)
x(i) = rangex(i+1,1)
y(i) = rangey(i+1,1)
next
'make helper arrays
redim dx(ubound(x)-1) as double
redim dy(ubound(x)-1) as double
redim dxyx(ubound(x)-1) as double
redim dxyy(ubound(x)-1) as double
for i = lbound(x) to ubound(x)-1
dx(i) = x(i+1) - x(i)
dy(i) = y(i+1) - y(i)
dxyx(i) = (x(i+1) + x(i))/2
dxyy(i) = dy(i) / dx(i)
next
'approximate b
s = 0
errcnt = 0
for i = lbound(dxyx) to ubound(dxyx)-1
on error goto errorhandler
s = s + log(abs(dxyy(i+1) / dxyy(i))) / (dxyx(i+1) - dxyx(i))
on error goto 0
next
b = s / (ubound(dxyx) - errcnt)
'approximate a
s = 0
errcnt = 0
for i = lbound(dx) to ubound(dx)
on error goto errorhandler
s = s + dy(i) / (exp(b * x(i+1)) - exp(b * x(i)))
on error goto 0
next
a = s / (ubound(dx) + 1 - errcnt)
'approximate c
s = 0
errcnt = 0
for i = lbound(x) to ubound(x)
on error goto errorhandler
s = s + y(i) - a * exp(b * x(i))
on error goto 0
next
c = s / (ubound(x) + 1 - errcnt)
'make y for (y - c) = a*e^(b*x)
for i = lbound(x) to ubound(x)
y(i) = log(abs(y(i) - c))
next
'get a and b from LINEST for (y - c) = a*e^(b*x)
oFunctionAccess = createUnoService( "com.sun.star.sheet.FunctionAccess" )
args = array(array(y), array(x))
ab = oFunctionAccess.CallFunction("LINEST", args)
if a < 0 then a = -exp(ab(0)(1)) else a = exp(ab(0)(1))
b = ab(0)(0)
trendExpPlusC = array(a, b, c)
exit function
errorhandler:
errcnt = errcnt + 1
resume next
end function