如何用函数递归填充数组?

时间:2015-06-02 20:38:56

标签: arrays matlab function recursion

所以我正在尝试编写一个函数来生成Hermite多项式,并且它正在做一些非常疯狂的事情......当我开始使用不同的h时,为什么会为n生成不同的元素?所以输入Hpoly(2,1)会给出

h = [ 1, 2*y, 4*y^2 - 2]

Hpoly(3,1)

h = [ 1, 2*y, 4*y^2 - 4, 2*y*(4*y^2 - 4) - 8*y]

((4y ^ 2 - 2 )vs(4y ^ 2 - 4 )作为第三个元素)

另外,我无法弄清楚如何实际评估表达式。我试过out = subs(h(np1),y,x),但没有做任何事。

代码:

function out = Hpoly(n, x)
clc;

syms y

    np1 = n + 1;
    h = [1, 2*y];
    f(np1)

    function f(np1)
        if numel(h) < np1
             f(np1 - 1)
             h(np1) = 2*y*h(np1-1) - 2*(n-1)*h(np1-2);
        end
    end
h
y = x;
out = h(np1);

end

-------------------------- EDIT -------------------- --------

所以我通过使用while循环来解决这个问题。我想知道为什么另一种方式不起作用...(并且仍然无法弄清楚如何评估表达式而不仅仅是从一开始就插入x ...我想这并不重要,但仍然会很高兴知道...)

可悲的是,我的代码没有hermiteH那么快:(我想知道为什么。

function out = Hpoly(n, x)

    h = [1, 2*x];
    np1 = n + 1;

    while np1 > length(h)
        h(end+1) = 2*x*h(end) - 2*(length(h)-1)*h(end-1);
    end

out = h(end)

end

1 个答案:

答案 0 :(得分:3)

为什么你的代码更慢?递归不一定是Matlab的强项,所以你可以使用recurrence relation来改进它。但是,hermiteH是用C语言编写的,你的循环不会像现在这样快,因为你使用的是while而不是for并且不必要地重新分配内存而不是预先分配内存。 hermiteH甚至可以对第一个系数使用查找表,或者可以使用explicit expression从矢量化中受益。我可能会像这样重写你的函数:

function h = Hpoly(n,x)
% n - Increasing sequence of integers starting at zero
% x - Point at which to evaluate polynomial, numeric or symbolic value
mx = max(n);
h = cast(zeros(1,mx),class(x)); % Use zeros(1,mx,'like',x) in newer versions of Matlab
h(1) = 1;
if mx > 0
    h(2) = 2*x;
end
for i = 2:length(n)-1
    h(i+1) = 2*x*h(i)-2*(i-1)*h(i-1);
end

然后您可以使用

调用它
syms x;
deg = 3;
h = Hpoly(0:deg,x)

返回[ 1, 2*x, 4*x^2 - 2, 2*x*(4*x^2 - 2) - 8*x](如果需要,请在输出中使用expand)。不幸的是,如果x具有象征性,这将不会快得多。

如果您只对在特定值处评估的多项式的数值结果感兴趣,那么最好完全避免使用符号数学。对于双精度x,上述函数的值比符号x快三到四个数量级。例如:

x = pi;
deg = 3;
h = Hpoly(0:deg,x)

产量

h =

   1.0e+02 *

   0.010000000000000   0.062831853071796   0.374784176043574   2.103511015993210


注意:

hermiteH函数是R2015a +,但假设您仍然可以访问符号数学工具箱而Matlab version是R2012b +,您也可以尝试调用MuPAD的orthpoly::hermitehermiteH在引擎盖下使用了这个功能。有关如何从Matlab调用MuPAD函数的详细信息,请参阅here。此函数稍微简单一点,因为它只返回一个单词。使用for循环:

syms x;
deg = 2;
h = sym(zeros(1,deg+1));
for i = 1:deg+1
    h(i) = feval(symengine,'orthpoly::hermite',i-1,x);
end

或者,您可以使用map对上述内容进行矢量化:

deg = 2;
h = feval(symengine,'map',0:deg,'n->orthpoly::hermite(n,x)');

两者都返回[ 1, 2*x, 4*x^2 - 2]