这个MATLAB代码有什么问题?

Nic*_*k_R 3 matlab concatenation dimensions

我想在MATLAB中做以下,

global a b c d e f g h l;
A=[1 3;3 2];
B=[a 0;0 b];
C=[d 0;e f];
Ctranspose=transpose(C);
D=[sqrt(d) 0;0 sqrt(f)];
E=Ctranspose/D;
Etranspose=transpose(E);
K=A+E;
M=E*D*Etranspose;

for a=1:10
  for b=1:10
    if  K==M
      print(a);
      print(b);
      print(d);
      print(e);
      print(f);
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

一个)

Error using  + 
Matrix dimensions must agree.

Error in trial (line 6)
K=A+B
Run Code Online (Sandbox Code Playgroud)

b)

Error using vertcat
CAT arguments dimensions are not consistent.

Error in trial (line 5)
C=[d 0;e f];
Run Code Online (Sandbox Code Playgroud)

这有什么不对?

(请注意,我是MATLAB的新手)

谢谢

Rod*_*uis 38

哎哟! 哎哟!让我直接跳到那里,在你继续沿着这条道路前打断你!

我知道你不是程序员,但在生活中的某些时刻(显然,这是你的!),你必须面对事实并成为一个,不管是暂时的.所以要知道编程不是真正的科学,它是一种艺术,如果你愿意的话,是一种手艺,而且很容易出错.还要知道,在你面前有数以百万计的程序员,他们为你铺平了道路,发现哪种方法效果最好,哪种方法导致了某些灾难.

我将描述代码中存在的其中六个"道路到某些厄运".

首先在列表中,是使用global.不要使用全局变量!! 当然,它们对于小而简单的事情都是正确的,但是更好,更易于管理,更耐用,更健壮,更不容易出错的传递数据的方式就是手动完成.根据经验,创建所有顶级函数,尽可能少依赖其他函数/变量.这是因为全局变量在程序的状态和函数的输出之间产生紧密耦合,这使得重现任何错误(如果不是不可能的话)和调试(这实际上是程序员花费他/她的大部分时间)完全噩梦.此外,除了正在运行的任何功能之外的任何功能都可以改变它们

function testMe
    global a;
    a = 5*rand;
    someFunction;
    b = 4*a; % ERROR! or...will it? 

function someFunction
    global a;
    a = a/5;
    if a < 0.5
        someOtherFunction; end

function someOtherFunction;
    global a;
    a = {'my string'};  
Run Code Online (Sandbox Code Playgroud)

有时工作,有时失败.可能发生的更糟糕事情的一个例子:

function testMe
    global a, b;
    a = 5; b = 6;
    result = someCalculation;
    result = a*b*result;


function someFunction
    global a;
    a = sin(pi/rand); % INTENTIONAL

    % do LOTS of stuff here

    for a = 1:10 % OOPS! unintentional use of variable name
        % do stuff
        if (some weird condition)
            break; end
    end
Run Code Online (Sandbox Code Playgroud)

没有错误,没有警告,什么都没有,但你的结果仍然是垃圾.随着您的功能变得越来越大(通常也会这样),这个错误变得越来越难以找到.花几天时间来发现这种错误并不罕见.

在您的代码中,您还可以更改全局变量ab循环内部.这意味着任何使用a此完成b调用的函数/脚本都将看到和.现在假设你这些循环中调用一个函数,它改变了它的值.在-loop 的下一次迭代中,它的价值是多少?假设你也得到了错误的结果.你会如何找到这个错误?a=10b=10aaa

像这样的代码通常被称为"意大利面条代码",原因很明显.也许它会起作用,并且很容易编码,但最终它会让你大大减慢速度(更不用说继承你代码的人了).

防止大部分这种情况的更好方法是在较大的容器中收集数据,并明确地传递它们.假设我们使用a struct作为数据a-l:

data = struct(...
    'a', a,...
    'b', b,...
    'c', c,...
    'd', d,...
    'e', e,...
    'f', f,...
    'g', g,...
    'h', h,...
    'l', l);
Run Code Online (Sandbox Code Playgroud)

所以你可以说

result = myFunction(data);
Run Code Online (Sandbox Code Playgroud)

内部访问数据myFunction是这样的:data.a以获取价值a,或data.f为价值f等说data.k = 5;myFunction 是不会改变result,还是原来的data传递给函数-你已经打破了紧耦合,并阻止所有上述问题.

键入help structhelp cell在Matlab命令窗口中了解这些类型的通用容器.

列表中的第二个是使用变量名称l.这有些愚蠢,我可以简短地说:不要这样做:)与大多数人(甚至是一些程序员)相信的情况相反,你只编写了一行代码,但你了数百个,如果不是数千个时间.最佳做法是尽可能简化阅读,而不是写作.该l只是看起来像1,不是吗?该bug k=1VS k=l仅仅是难度比现货k=mVS k=1.

列表中的第三个是关键字transpose.这有点啰嗦,不是吗?在数学中,你会使用A T,这比在所有时间写完整定义要容易得多:

B = {A IJ ➝A ∀我<M⋏Ĵ<N

你通常只说B = A 牛逼.在Matlab中也是如此.所述transpose矩阵可以实现像这样:

Actrans = A' ; % conjugate transpose
Atrans  = A.'; % regular transpose
Run Code Online (Sandbox Code Playgroud)

这会将您的代码减少到更简洁

A = [1 3;3 2];
B = [a 0;0 b];
C = [d 0;e f];    
D = [sqrt(d) 0;0 sqrt(f)];
E = C.'/D;    
K = A+E;
M = E*D*E.';
Run Code Online (Sandbox Code Playgroud)

名单上的第四位是平等K==M.它就在这里,K而且M矩阵.表达式K==M求值逐元素,其原因后面将变得明显在编程生涯:)这意味着,K==M将再次的矩阵,尺寸相同K,并M包含0如果对应于元件KM不相等,并且1如果这些元素是平等的.那么,if陈述会对这样一个矩阵做什么呢?在Matlab中,true只要第一个元素为真(在我看来,它应该抛出一个错误,但是哦).

这显然不是你想要的.我认为你想要的是两个矩阵中的所有元素是相等的.你最好用这个:

if all( abs(K(:)-M(:)) < eps )
Run Code Online (Sandbox Code Playgroud)

其中(:)-notation表示矩阵K,M应在比较之前扩展为列向量.这是因为all()作品落单的尺寸,所以all(K==M)仍然是一个矩阵(向量,实际上,但这是同一事物的一种特殊情况下使用不同的名称).请注意,我不使用equality(==),而是检查它们的差异是否小于某个微小的值(eps).这是因为在浮点运算(所有计算机都使用)中,乘法和平方根等运算通常会遇到舍入误差和近似/插值误差等问题.一个平等是一个非常艰难的需求,过于强硬,以评估true在大多数情况下,它在数学上应该说.您可以通过将两者的差异与一个与舍入误差(eps)相关的微小值进行比较来防止此失败检测到相等性.

列表中的第五位是您打印的方式.该print声明,其本身将发送数字到系统的默认打印机,你知道,关于它,如果它感觉就像今天的合作与墨水吐出来的纸张穆迪机:)现在,我假设你试图显示上的东西屏幕.这样做就像你开始展示事物的方式不是最好的方法:你会得到十几个未命名的非结构化值列表:

1     % which would be the value of 'a'
1     % which would be the value of 'b'
3     % which would be the value of 'd'
4     % which would be the value of 'e'
5     % which would be the value of 'f'
...
Run Code Online (Sandbox Code Playgroud)

只看到这些值会使阅读和解释正在发生的事情变得相当繁琐.更好地使用更具描述性的内容:

if all( abs(K(:)-M(:)) < eps )

    % option 1
    a
    b
    d   % NOTE: not terminating with semicolon
    e
    f

    % option 2
    fprintf(...
        'a: %d\n, b: %d\n, d: %d\n, e: %d\n, f: %d\n\n', a,b,d,e,f); 

end
Run Code Online (Sandbox Code Playgroud)

选项1将只显示

a = 
    1
b = 
    1
etc.
Run Code Online (Sandbox Code Playgroud)

至少还会显示变量的名称及其值.选项2是更好的选择:

a: 1
b: 1
d: 3
e: 4
f: 5

a: 1
b: 2
d: 3
e: 4
f: 5

etc.
Run Code Online (Sandbox Code Playgroud)

(顺便说a,b,d,e,f 一下,循环中的值永远不会改变,那么为什么要首先显示它们呢?)

列表中的第六个(也是最后一个!)是特定于Matlab的一个:for-loops.Matlab是一种基于矩阵的解释语言.它的矩阵性质只意味着每个变量本质上都是一个矩阵.解释意味着计算机的处理器不会直接看到您的代码,在计算任何内容之前,它必须经过一系列的解释和翻译.这枚硬币有两面:

  • 它可以加快速度(比如编码或做"琐碎"的事情,如求解线性系统,FFT,矩阵比较等)
  • 它可以减慢速度(比如重复执行语句,比如在循环中)

根据性能,for-loop在Matlab中因为将操作带入爬行而臭名昭着.在Matlab中的方法通常是矢量化代码,例如,使用所有变量都是矩阵的事实,并对它们使用矩阵/张量运算而不是循环.这在大多数编程语言中并不是一种非常常见的方法(并且在不习惯它的程序员中会看到很多强大的,强烈的阻力),但在数学上下文中它很有意义.在求助于for循环之前,总是尝试使用矩阵/张量操作作为第一道攻击线(并且Matlab有很多它们,请注意!).

所以,有什么错你的代码:)噢,和安德烈亚斯Hangauer已经提到,将参照声明a通过l,和所有需要被accordinly重新计算,循环内部,你会被罚款.