Matlab:for 循环内对列的算术运算(简单但曲折!)

Matlab: arithmetic operation on columns inside a for loop (simple yet devious!)

我试图表示一个简单的矩阵 m*n(假设它只有一行!)使得 m1n1 = m1n1^1, m1n2 = m1n1^2, m1n3 = m1n1^3, m1n3 = m1n1 ^4, ... m1ni = m1n1^i。 换句话说,我试图遍历矩阵列 n 次以在末尾添加一个新向量(列),以便每个索引都具有与第一个向量相同的值,但提高到其列号的幂n.

这是原始向量:

v=
    1.2421
    2.3348
    0.1326
    2.3470
    6.7389
这是第三次迭代后的 v:

v=
    1.2421 1.5429 1.9165
    2.3348 5.4513 12.7277
    0.1326 0.0176 0.0023
    2.3470 5.5084 12.9282
    6.7389 45.4128 306.0329
现在考虑到我完全是 Matlab 的菜鸟,我真的低估了这样一个看似简单的任务的难度,我花了将近一天的调试和网上冲浪来寻找任何线索。这是我想出的:

rows = 5;
columns = 3;
v = x(1:rows,1);
k = v;
Ncol = ones(rows,1);
extraK = ones(rows,1);

disp(v)

for c = 1:columns
    Ncol = k(:,length(k(1,:))).^c; % a verbose way of selecting the last column only.
    extraK = cat(2,extraK,Ncol);
end

k = cat(2,k,extraK);
disp(extraK(:,2:columns+1)) % to cut off the first column

现在这段代码(出于某种奇怪的原因)仅在行数等于或小于 6 且列数等于或小于 3 时才有效。

当行数 = 7 时,这是输出:

v = 1.0e+03 *

0.0012    0.0015    0.0019
0.0023    0.0055    0.0127
0.0001    0.0000    0.0000
0.0023    0.0055    0.0129
0.0067    0.0454    0.3060
0.0037    0.0138    0.0510
0.0119    0.1405    1.6654

我怎样才能在任意数量的行和列上达到 运行?

谢谢

我发现您的代码有几个问题:

  1. 我不确定你为什么定义 d = 3;。这只是吹毛求疵,但您可以安全地将其从代码中删除。
  2. 您没有正确进行电源操作。具体看这个说法:

    Ncol = k(:,length(k(1,:))).^c; % a verbose way of selecting the last column only.
    

    您选择性地选择了最后一列,这很好,但是您没有正确应用电源操作。如果我理解您的说法,您希望采用 原始 向量,并执行 n 次幂的幂运算,其中 n 是当前迭代。因此,您真的只需要这样做:

    Ncol = k.^c;
    

    Ncol 替换为以上行后,代码现在应该可以工作了。我还注意到您裁剪了结果的第一列。您获得重复列的原因是因为您的 for 循环从 c = 1 开始。由于您已经计算了 v.^1 = v,因此您可以在 c = 2 处开始循环。将循环起点更改为 c = 2,您就可以摆脱第一列的删除。


但是,我将在一行代码中以另一种方式执行此操作。在我们这样做之前,让我们先了解一下您正在尝试做的事情的理论。

给定一个向量 v,即 m 个长期存储在 m x 1 向量中的元素,您想要的是一个大小为 m x n 的矩阵,其中 n 是所需的列数,对于从左到右开始的每一列,您希望将 v 乘以 nth 次方。

因此,根据第三个 "iteration" 中的示例,第一列表示 v,第二列表示 v.^2,第三列表示 v.^3


我将向您介绍 bsxfun 的强大功能。 bsxfun代表Binary Singleton EXpansion函数。 bsxfun 的作用是,如果您有两个输入,其中一个或两个输入具有单一维度,或者如果两个输入中的任何一个具有 一个值为 1 的维度,每个输入都在其单例维度中复制以匹配另一个输入的大小,然后对这些输入一起应用逐元素操作以生成输出。

例如,如果我们有两个像这样的向量:

A = [1 2 3]

B = [1
     2
     3]

注意其中一个是行向量,一个是列向量。 bsxfun 会看到 AB 都有单例维度,其中 A 的单例维度是行数为 1,而 B 有单例维度,即列数为 1。因此,我们将复制 BA 中一样多的列,并复制 A 与 [=] 中一样多的行41=],我们实际上得到:

A = [1 2 3
     1 2 3
     1 2 3]

B = [1 1 1
     2 2 2
     3 3 3]

一旦我们有了这两个矩阵,您就可以对这些矩阵应用任何元素明智的操作来获得您的输出。例如,您可以加、减、取幂或进行元素明智的乘法或除法。


现在,这种情况如何适用于您的问题如下。你正在做的是你有一个向量 v,你将有一个 矩阵 的幂,如下所示:

M = [1 2 3 ... n
     1 2 3 ... n
     ...........
     ...........
     1 2 3 ... n]

基本上,我们将有一个 1 列,然后是一个 2 列,直到您想要的列数 n。我们将 bsxfun 应用到向量 v 上,它是一个列向量,另一个向量只是 单行 值从 1 到 n.您将应用电源操作来实现您的结果。因此,您可以通过以下方式方便地计算输出:

columns = 3;
out = bsxfun(@power, v, 1:columns);

让我们根据您的向量尝试几个示例 v:

>> v = [1.2421; 2.3348; 0.1326; 2.3470; 6.7389];
>> columns = 3;
>> out = bsxfun(@power, v, 1:columns)

out =

    1.2421    1.5428    1.9163
    2.3348    5.4513   12.7277
    0.1326    0.0176    0.0023
    2.3470    5.5084   12.9282
    6.7389   45.4128  306.0321

>> columns = 7;
>> format bank
>> out = bsxfun(@power, v, 1:columns)

out =

  Columns 1 through 5

          1.24          1.54          1.92          2.38          2.96
          2.33          5.45         12.73         29.72         69.38
          0.13          0.02          0.00          0.00          0.00
          2.35          5.51         12.93         30.34         71.21
          6.74         45.41        306.03       2062.32      13897.77

  Columns 6 through 7

          3.67          4.56
        161.99        378.22
          0.00          0.00
        167.14        392.28
      93655.67     631136.19

请注意,为了将列设置为 3,我们得到了在您的 post 中看到的内容。为了将列数增加到 7,我不得不更改数字的显示方式,以便您可以清楚地看到数字。不这样做会使它变成指数形式,并且有效数字后面有很多零。


祝你好运!

计算累积幂时,您可以重用以前的结果:对于标量 xnx.^n 等于 x * x.^(n-1),这里已经得到了x.^(n-1)。这可能比单独计算每个幂更有效,因为乘法比幂快。

N 为所需的最大指数。要使用所描述的方法,列向量 v 水平重复 N 次 (repmat), and then a cumulative product is applied along each row (cumprod):

v =[1.2421; 2.3348; 0.1326; 2.3470; 6.7389]; %// data. Column vector
N = 3; %// maximum exponent
result = cumprod(repmat(v, 1, N), 2);