【问题标题】:Indexing a smaller matrix into the center of a larger matrix [duplicate]将较小的矩阵索引到较大矩阵的中心[重复]
【发布时间】:2019-05-16 15:15:31
【问题描述】:

我正在尝试以下作为一种爱好,而不是家庭作业。我是 MATLAB 新手,一般编码知识有限。我有一个问题,我被困住了。来自使用 MATLAB 进行计算机编程:J. Michael Fitzpatrick 和 Akos Ledeckzi

问题 10. 编写一个名为 cancel_middle 的函数,它接受 A,一个 n-by-m 矩阵,作为输入,其中 nm 都是奇数,k 是正数 小于 mn 的奇数(函数不必 检查输入)。该函数返回输入矩阵,其中心 kk 矩阵归零。看看下面的运行,

>> cancel_middle(ones(5),3)
ans =
 1 1 1 1 1
 1 0 0 0 1
 1 0 0 0 1
 1 0 0 0 1
 1 1 1 1 1

我有一个可以正确执行输入参数的嵌套 if 函数,但我无法获得所需的输出。我相信它远没有效率,我使用 if 语句,即使它没有在书中涉及。这是我以前的知识。所以我认为有一个更简单、更高效的函数要编写。

function M = cancel_middle(A,k);

[m,n] = size(A);
if rem([m,n],2) == [1,1]
    if rem(k,2)==1
        if [k,k]<[m,n]
            M = zeros(k);

        else
            fprintf('Error 1: k must be odd and smaller than A\n');
        end
    else
        fprintf('Error 2: k must be odd and smaller than A\n');
    end
else
    fprintf('Error 3: k must be odd and smaller than A\n');
end

我坚持的区域是应该在第 8 行的输出参数。我正确地输出了 k×k 矩阵,但由于显而易见的原因,它不在更大的矩阵上。我相信我想将矩阵 zeros(k) 索引到更大的矩阵 A 上。我相信我缺少一些关键函数,这些函数也可以让我免于使用 3 个 if 语句,但我对此一无所知.

这是我运行函数时的输出:

>> cancel_middle(ones(5),3)
ans =
     0     0     0
     0     0     0
     0     0     0

显然它只是 zeros(k) 输出。

【问题讨论】:

  • 到目前为止,您的大部分代码似乎都在检查输入(您的问题并不特别要求)。与其创建一个单独的零矩阵,不如考虑如何计算 A 的哪些元素应该变为零的索引并直接设置它们......
  • @etmuse 我正在运行这些检查,因此该函数可以确定输入是否确实是问题所要求的。因此,如果我输入一个大小为 4×4 的矩阵,我会按预期得到一个错误。我确实喜欢您将 A 的指定元素更改为零而不是创建单独的零矩阵的方法。谢谢
  • 我建议阅读 thisthis 以熟悉索引,因为这将是解决此类问题的关键。
  • @SardarUsama,是的!绝对是一个强大的副本。这个任务必须是重复的......

标签: arrays matlab matrix indexing


【解决方案1】:

我不知道您是否已经了解了 MATLAB 的 索引 部分,但如果没有,我强烈建议您阅读它们,因为这是 MATLAB 优势的支柱之一:

一旦理解了这一点,练习就是计算矩阵的哪些索引将归零。获得索引列表后,将值分配给位于这些位置的矩阵元素是一项简单的分配。

考虑下面的函数(请原谅冗长和冗长的变量名,但我试图让它具有指导意义)。每行末尾以 cmets 给出的结果值对于输入 A=ones(5,7)k=3 的示例集有效:

function M = cancel_middle(A,k)

    % find [m,n] (the size of A)
    [m,n] = size(A) ; % => m=5, n=7

    % calculate the coordinates of the "center" of the matrix
    center_row_idx = (m+1)/2  ; % => center_row_idx = 3
    center_col_idx = (n+1)/2  ; % => center_col_idx = 4

    % how much indices to take on each side of the center
    half_width = (k-1)/2 ;      % => center_row_idx = 3

    % generate the indices which will be zeroed
    row_indices = center_row_idx-half_width:center_row_idx+half_width ; % => row_indices = [2,3,4]
    col_indices = center_col_idx-half_width:center_col_idx+half_width ; % => col_indices = [3,4,5]

    % generate the output matrix M (as a copy of A)
    M = A ;
    % now you can zero the elements of matrix M directly by their indices
    M(row_indices,col_indices) = 0 ;

end

您可以验证:

>> M = cancel_middle(ones(5,7),3)
M =
     1     1     1     1     1     1     1
     1     1     0     0     0     1     1
     1     1     0     0     0     1     1
     1     1     0     0     0     1     1
     1     1     1     1     1     1     1

【讨论】:

    【解决方案2】:

    您可以将索引分配与end 一起使用,如下所示:

    A = randi(9,5,7); % example A
    k = 3; % example k
    t = -(k-1)/2:(k-1)/2;
    A((end+1)/2 + t, (end+1)/2 + t) = 0;
    

    示例结果:

    A =
         2     5     2     9     3     6     9
         6     3     0     0     0     4     8
         7     7     0     0     0     8     5
         6     2     0     0     0     5     6
         5     7     1     5     8     4     6
    

    【讨论】:

    • 代码高尔夫对你的影响太大了 Luis :-) 但无论如何 +1 是一个很好的技巧 end 关键字。
    • @Hoki Nah。打高尔夫球的版本是t=1-k/2:k/2;A(end/2+t,end/2+t)=0 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-01
    • 1970-01-01
    相关资源
    最近更新 更多