【问题标题】:input element 1 by 1 from other function w/o for loop来自其他函数的输入元素 1 by 1 w/o for 循环
【发布时间】:2012-06-15 22:11:42
【问题描述】:

我有一个函数可以计算一个数字数组(randparam),我想将它逐个元素地输入到另一个进行模拟的函数中。

例如

function [randparam] = arraycode

code 

randparam = results of code 
% randparam is now a 1x1001 vector. 

end

接下来我想将 randparam 1 by 1 输入到我的模拟函数中

function simulation 

x = constant + constant * randparam + constant

return 
end

让我觉得困难的是因为模拟函数中的return命令,它只计算上面方程x的一步,将结果返回到另一个函数,调用它积分器,然后积分器函数会调用模拟再次使用函数来计算 x。

所以积分函数可能看起来像

function integrator (x)
y = simulation(x) * 5
u = y+10
yy = simulation(x) * 10 + u

end

如您所见,积分函数调用模拟函数两次。这给我带来了两个问题:

  1. 如果我在模拟函数中创建一个 for 循环,在该循环中我使用类似的方式逐个元素地输入:

    对于 i = 1:100

    x = 常数 + 常数 * randparam(i) + 常数

    返回
    结束

然后每次我的积分器函数再次调用我的模拟函数时,我的 for 循环都会从 1 重新开始。

2.如果我以某种方式将 i 保留在我的基础工作区中,以便我的模拟函数中的 for 循环知道从 1 开始,那么我的 y 和 yy 函数将具有不同的 x 输入,因为只要它会第二次为 yy 打电话,那么由于 y 的电话,我现在是 i+1。

在这种情况下有没有办法避免 for 循环?第二个问题的一个潜在解决方案是复制脚本但使用不同的名称,并让我的 for 循环使用不同的变量,但这似乎效率很低。

希望我说清楚了。

谢谢。

【问题讨论】:

    标签: function matlab for-loop scope


    【解决方案1】:

    首先,如果您通常希望对数组的每个元素应用相同的函数,并且还没有内置的矢量化方法,您可以 使用arrayfun(虽然通常一个简单的for 循环更快、更易读):

    %# randparam is a 1x1001 vector. 
    %#next I want to input randparam 1 by 1 into my simulation function
    function simulation 
        x = constant + constant * randparam + constant
        return 
    end
    

    (注意:问问自己这个函数可能在做什么,因为它没有返回值,而且 MATLAB 也没有通过引用传递。)这就是 arrayfun 的用途:将函数应用于一个数组(或向量,在这种情况下)。同样,您应该确保在您的情况下这样做是有意义的,而不是显式循环。

    function simulation(input_val)
    #% your stuff
    end
    
    
    sim_results = arrayfun( @simulation, randparam);
    

    当然,你写的方式,行

    x = constant + constant*randparam + constant;
    

    可以(并且将)进行矢量化 - 如果你给它一个矢量或矩阵,一个矢量或矩阵将是结果。

    第二您似乎对MATLAB中函数变量的“范围”不清楚。如果调用函数,则会创建一个干净的工作区。因此,来自一个函数的x 在您调用的另一个函数中不会自动可用。变量也会在函数末尾超出范围,因此在函数内使用 x 不会更改/覆盖该函数外部存在的变量 x。并且对一个函数的多次调用每个都有自己的工作区

    【讨论】:

    • 这个“第一”点无效。 arrayfun 通常比 for 循环慢,假设内存是预先分配的。例如,y = arrayfun(@sin, x)y = zeros(1, numel(x)); for j = 1:numel(x); y(j) = sin(x(j)); end
    • @RobDiPietro 根据我的经验这是正确的;但是问题指定了“不带循环”。正如我所指出的,simulation 函数中的操作隐式支持矢量化形式。
    • 确实如此;也许答案应该改写一下。我认为您回答的第一部分强烈建议arrayfun 是在数组上应用函数的正确方法,但实际上这会产生较慢的可读性较差的代码。
    • @RobDiPietro 已编辑。我同意在一维数组的情况下,arrayfun 的可读性可能会降低,尽管我认为任何经常使用 MATLAB 的人都会很容易正确地看到操作。对于 N 维数组,它通常比 N 层嵌套的 for 循环更具可读性。不过,当谈到这个问题时,我怀疑变量范围的问题对提问者来说更为重要。复制脚本并使用不同的变量名的建议肯定是这样的。
    • 您好 tmpearce,感谢您的回复。我在变量范围方面遇到困难,我不确定如何正确实现 arrayfun 函数。我想用 for 循环可能更容易做到这一点。我只是想确保我清楚,但是我不想传递随机参数的 1x1001 向量并以向量化的方式计算它。我逐个元素需要它的原因是,使用随机参数值的特定计算被多次调用以产生最终结果,并以逐步方式计算。我将不得不更改大部分代码
    【解决方案2】:

    积分器级别的循环有什么问题?

    function integrator (x)
    
    for i=1:length(x)
        y = simulation(x(i)) * 5
        u = y+10
        yy = simulation(x(i)) * 10 + u
    end
    

    然后将您的整个 randparm 传递给积分器?从您的问题中不清楚您是否希望 simulation 在给定相同的输入时返回相同的值,或者您是否希望它使用相同的输入执行两次,或者您是否希望每次调用都有新的输入。也不清楚simulation 是否保持任何内部状态。根据您编写示例的方式,模拟仅取决于输入值,而不取决于任何先前的输入或输出,这使得矢量化变得微不足道。如果我们都错过了这条船,请使用更精致的示例代码编辑您的问题。

    【讨论】:

    • 对不起,彼得,你说得对,我没有清楚地说明问题。当我正要尝试重新定义我的问题时,我意识到我可以尝试其他一些方法,并且它奏效了,但它与你的回答一致。非常感谢您的宝贵时间。
    猜你喜欢
    • 2023-04-10
    • 2014-01-08
    • 2016-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多