Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 向量化涉及while循环或循环中if子句的函数(Matlab)_Arrays_Matlab_Loops_Conditional Statements_Vectorization - Fatal编程技术网

Arrays 向量化涉及while循环或循环中if子句的函数(Matlab)

Arrays 向量化涉及while循环或循环中if子句的函数(Matlab),arrays,matlab,loops,conditional-statements,vectorization,Arrays,Matlab,Loops,Conditional Statements,Vectorization,假设我有一个函数,可以从一个输入计算一个输出,例如 function y = sqrt_newton(x) y = x ./ 2; yo = y; y = 0.5.*(y + x ./ y); while abs(y - yo) > eps * abs(y) yo = y; y = 0.5.*(y + x ./ y); end end 我希望能够将此函数应用于向量输入,比如说sqrt\u newton(2:9)类似于

假设我有一个函数,可以从一个输入计算一个输出,例如

function y = sqrt_newton(x)
    y = x ./ 2;
    yo = y;
    y = 0.5.*(y + x ./ y);
    while abs(y - yo) > eps * abs(y)
        yo = y;
        y = 0.5.*(y + x ./ y);
    end
end
我希望能够将此函数应用于向量输入,比如说
sqrt\u newton(2:9)
类似于内置函数。在循环开始时使用一个条件或内部的一些if子句来实现这一点的最佳方法是什么?如果可能的话,我希望避免编写一个额外的函数作为包装器来循环输入向量

我当前繁琐的解决方案

到目前为止,我所做的是:

  • 我必须首先将输入扩展到相同的大小(使用finance toolbox中的finargsz,但是如果您知道另一个核心函数也可以这样做,那就太好了)

  • 使用
    size

  • 交易
    输入

  • 循环遍历所有输入元素

  • 重塑输出


似乎
numel
函数减轻了所有这些繁重的工作,但额外的注释将是最受欢迎的。

我认为,由于函数操作的未知特性,通常必须使用循环。如果是线性运算,矢量化是可能的

对于您的示例,我将使用以下内容:

function y = sqrt_newton(x)
    y = x ./ 2;
    yo = y;
    y = 0.5.*(y + x ./ y);
    for i=1:numel(x)
        while abs(y(i) - yo(i)) > eps * abs(y(i))
            yo(i) = y(i);
            y(i) = 0.5*(y(i) + x(i) / y(i));
        end
    end
end
我使用numel,而不是size,因此它可以处理我扔给它的任何数组

那么,您可以按如下方式对它进行矢量化(使用
any
):

然后你会得到:

>> sqrt_newton(2:9)
ans =
    1.4142    1.7321    2.0000    2.2361    2.4495    2.6458    2.8284    3.0000

>> ans.^2-(2:9)
ans =
   1.0e-14 *
   -0.0444   -0.0444         0    0.0888   -0.0888    0.0888   -0.1776         0
正如所料。但是,我不建议这样做,因为您正在对已经聚合的元素执行不必要的操作。我会在函数的开头使用
for
循环
x

function yall = sqrt_newton(xall)
yall = zeros(size(xall));
for xn=1:numel(xall)
    x = xall(xn);
    y = x / 2;
    yo = y;
    y = 0.5*(y + x ./ y);
    while abs(y - yo) > eps * abs(y)
        yo = y;
        y = 0.5*(y + x ./ y);
    end
    yall(xn)=y;
end
end
在开始时设置大小
yall
,以避免在整个循环中它的大小增加。

始终存在。您可以保留现有代码,将其放入内部函数中

function y = sqrt_newton(z)

    y = arrayfun(@inner, z);

    function y= inner(x)
        y = x ./ 2;
        yo = y;
        y = 0.5.*(y + x ./ y);
        while abs(y - yo) > eps * abs(y)
            yo = y;
            y = 0.5.*(y + x ./ y);
        end
    end
end
编辑:上述解决方案的优点是,在使用1x1输入后,实现起来非常简单,但对于大输入,其他答案中的循环要快得多。例如,在我的计算机上

tic; sqrt_newton(rand(500)); toc

用我的代码运行
~1.24秒
,用@Ramashalanka的代码运行
0.06秒
,用@GuntherStruyf的代码运行
0.28秒。

好吧,我喜欢你的解决方案,因为它与原始函数相比开销最小。太糟糕了,它太慢了。事实上,我使用了类似的解决方案,但我希望有其他方法可以干净利落地做到这一点。见我在问题下的额外评论。
tic; sqrt_newton(rand(500)); toc