进行函数定义时,每次请求函数时都会重新计算函数的值。在某些类型的计算中,您最终可能会多次要求相同的函数值。通过让语言记住它找到的所有函数值,您可以节省时间。
对于其他语言,但是对于八度,我找不到:
这主要是为了在计算factorial
或Fibonacci
数字时优化递归函数调用。这就是为什么我们可以节省并消除他们拥有的指数复杂性。由于否则中间计算必须多次执行,导致指数复杂。
答案 0 :(得分:2)
正如您在问题中的MATLAB链接中简要提到的,您可以使用persistent变量来保留以前的计算。
这是一个测试函数,使用计算阶乘的例子:
function f = persistentFactorial(n)
% declare variable factorials to be persistent
persistent factorials
computed = numel(factorials);
if computed == 0
% function called for the first time; initialize first element
factorials(1) = 1;
computed = 1;
end
if n > computed
% fill in uncomputed factorials between computed and n
% fprintf('calculating factorials between %d and %d\n', computed+1, n);
factorials(computed+1:n) = computed+1:n;
factorials(computed:n) = cumprod(factorials(computed:n));
end
% return requested factorial
f = factorials(n);
end
如果您在取消注释fprintf
的情况下调用此函数,则可以得到如下内容:
>> persistentFactorial(5)
calculating factorials between 2 and 5 % <-- first call to function
ans = 120
>> persistentFactorial(5) % <-- second call; no new values
ans = 120
>> persistentFactorial(6)
calculating factorials between 6 and 6 % <-- third call; one new value
ans = 720
请注意,如果要清除持久变量,则无法直接从任何其他函数甚至命令窗口访问它,因此您无法键入clear factorials
。您必须清除功能本身(甚至只需编辑它):
clear persistentFactorial
答案 1 :(得分:0)
这是一个不同于@beaker的递归,使用Matlab / Octave persistent
变量来实现记忆功能。
仅在Octave
上进行测试,对于Matlab
版本,您需要将评论格式#
转换为%
,以及其他此类小修改。< / p>
可以在此GitHub存储库中找到完整代码:https://github.com/evandrocoan/ComputerScienceGraduation/tree/master/NumericalAnalysis/2016-2/Others/11.04_class22_Chebyshev
#
# Evaluate the t variable at the k'th Chebyshev Polynom
#
# i = 1 : n
# fChebyshev( i ) = b0*T0( t(i) ) + b1*T1( t(i) ) + b2*T2( t(i) ) + b3*T3( t(i) ) + ...
#
# @param k , the k'th Chebyshev Polynom.
# @param t , the value to evaluate at the k'th Chebyshev Polynom.
# @param isToDiscartTheSavedRecursion, true to indicate the current `t`'s Chebyshev Polynom sequence
# must to be discarded. You must to always discard the old
# sequence when a new `t` value is provided. Use false to
# preserve the `t` cached values and use the recursion remember
# feature.
#
function value = getChebyshevCoefficientsNumerically( k, t, isToDiscartTheSavedRecursion = true )
persistent chebyshevPolynomCoefficients;
chebyshevPolynomCoefficients;
t_size = numel( t );
computed = numel( chebyshevPolynomCoefficients );
# printf( 'Calling Chebyshev Polynom Coefficients with computed = %d, k = %d', computed, k );
# printf( 'and t_size: %d \n', t_size );
# When the function is called for the first time, initialize the first element and also reset
# the old data, when a new variable `t` is calculated.
if computed == 0 || isToDiscartTheSavedRecursion
# printf( '\n\n\n\n\n( getChebyshevCoefficientsNumerically ) Cleaning ' );
# printf( 'chebyshevPolynomCoefficients! computed: %d, k: %d\n', computed, k );
for i = 1 : t_size
chebyshevPolynomCoefficient( i ).vector = 1;
end
computed = 1;
chebyshevPolynomCoefficients = chebyshevPolynomCoefficient;
end
t_size;
t;
k;
chebyshevPolynomCoefficients.vector;
for i = 1 : t_size
# printf( '( getChebyshevCoefficientsNumerically ) Calculating the %dth t''s vector point.\n', i );
[ value( i ), chebyshevPolynomCoefficients( i ).vector ] = getnthChebyshevCoefficientsNumerically( ...
k, t( i ), chebyshevPolynomCoefficients( i ).vector );
end
end
#
# Efficient Computation of Chebyshev Polynomials in Computer Algebra
# http://www.mathematik.uni-kassel.de/koepf/cheby.pdf
#
# Mathematics 4330/5344–#5 Approximation of Functions
# http://texas.math.ttu.edu/~gilliam/ttu/m4330/m4330_5.pdf
#
# Are there functions that remember values they have found on Octave?
# http://stackoverflow.com/questions/40445316/are-there-functions-that-remember-values-they-have-found-on-octave
#
# @param k , the k'th Chebyshev Polynom.
# @param t , the value to evaluate at the k'th Chebyshev Polynom.
# @param chebyshevPolynomCoefficients, a vector within the cached Chebyshev Polynom sequences.
#
function [ result, chebyshevPolynomCoefficients ] = ...
getnthChebyshevCoefficientsNumerically( k, t, chebyshevPolynomCoefficients )
t;
computed = numel( chebyshevPolynomCoefficients );
# printf( '( getnthChebyshevCoefficientsNumerically ) Calling with computed = ' );
# printf( '%d and k = %d\n', computed, k );
# Compute in uncomputed `chebyshevPolynomCoefficients`. The indexes are `k + 1` shifted because
# the b's Chebyshev Polynom Coefficients starts on 0, but octave only allow indexes starting
# at 1. This starts calculating all the missing b's Chebyshev Polynom from the index `computed`
# until the requested coefficient `k`.
if k + 1 > computed
for i = computed : k
# printf( '( getnthChebyshevCoefficientsNumerically ) Starting computing the %d ', i );
# printf( 'coefficient of %d (k) coefficients.\n', k );
if i == 0
chebyshevPolynomCoefficients( i + 1, : ) = 1;
elseif i == 1
chebyshevPolynomCoefficients( i + 1, : ) = t;
elseif mod( i, 2 ) == 0
chebyshevPolynomCoefficients( i + 1, : ) = 2.*getnthChebyshevCoefficientsNumerically( ...
i/2, t, chebyshevPolynomCoefficients ).^2 .- 1;
else
chebyshevPolynomCoefficients( i + 1, : ) = 2.*getnthChebyshevCoefficientsNumerically( ...
(i-1) / 2, t, chebyshevPolynomCoefficients ).*getnthChebyshevCoefficientsNumerically( ...
(i+1) / 2, t, chebyshevPolynomCoefficients ) - t;
end
end
end
k;
chebyshevPolynomCoefficients;
result = chebyshevPolynomCoefficients( k + 1 );
end
这是一个示例输出,其中第9个Chebyshev系数激活了递归记忆功能,t = 0.6:
> T9_calcula = getChebyshevCoefficientsNumerically( 9, 0.6, false )
T9_correct = -0.472103423999999
Calling Chebyshev Polynom Coefficients with computed = 0, k = 9 and t_size: 1
( getChebyshevCoefficientsNumerically ) Cleaning chebyshevPolynomCoefficients! computed: 0, k: 9
( getChebyshevCoefficientsNumerically ) Calculating the 1th t's vector point.
( getnthChebyshevCoefficientsNumerically ) Calling with computed = 1 and k = 9
( getnthChebyshevCoefficientsNumerically ) Starting computing the 1 coefficient of 9 (k) coefficients.
( getnthChebyshevCoefficientsNumerically ) Starting computing the 2 coefficient of 9 (k) coefficients.
( getnthChebyshevCoefficientsNumerically ) Calling with computed = 2 and k = 1
( getnthChebyshevCoefficientsNumerically ) Starting computing the 3 coefficient of 9 (k) coefficients.
( getnthChebyshevCoefficientsNumerically ) Calling with computed = 3 and k = 1
( getnthChebyshevCoefficientsNumerically ) Calling with computed = 3 and k = 2
( getnthChebyshevCoefficientsNumerically ) Starting computing the 4 coefficient of 9 (k) coefficients.
( getnthChebyshevCoefficientsNumerically ) Calling with computed = 4 and k = 2
( getnthChebyshevCoefficientsNumerically ) Starting computing the 5 coefficient of 9 (k) coefficients.
( getnthChebyshevCoefficientsNumerically ) Calling with computed = 5 and k = 2
( getnthChebyshevCoefficientsNumerically ) Calling with computed = 5 and k = 3
( getnthChebyshevCoefficientsNumerically ) Starting computing the 6 coefficient of 9 (k) coefficients.
( getnthChebyshevCoefficientsNumerically ) Calling with computed = 6 and k = 3
( getnthChebyshevCoefficientsNumerically ) Starting computing the 7 coefficient of 9 (k) coefficients.
( getnthChebyshevCoefficientsNumerically ) Calling with computed = 7 and k = 3
( getnthChebyshevCoefficientsNumerically ) Calling with computed = 7 and k = 4
( getnthChebyshevCoefficientsNumerically ) Starting computing the 8 coefficient of 9 (k) coefficients.
( getnthChebyshevCoefficientsNumerically ) Calling with computed = 8 and k = 4
( getnthChebyshevCoefficientsNumerically ) Starting computing the 9 coefficient of 9 (k) coefficients.
( getnthChebyshevCoefficientsNumerically ) Calling with computed = 9 and k = 4
( getnthChebyshevCoefficientsNumerically ) Calling with computed = 9 and k = 5
T9_calcula = -0.472103424000000
但也可称为:
> T9_calcula = getChebyshevCoefficientsNumerically( 9, [ 0.6, 0.7, 0.3 ], false )