此MATLAB代码有什么问题? [英] What is wrong with this MATLAB code?

查看:106
本文介绍了此MATLAB代码有什么问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在MATLAB中执行以下操作

I am trying to do following in 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

我收到以下错误:

a)

Error using  + 
Matrix dimensions must agree.

Error in trial (line 6)
K=A+B

b)

Error using vertcat
CAT arguments dimensions are not consistent.

Error in trial (line 5)
C=[d 0;e f];

这是怎么了?

(请注意,我是MATLAB新手)

(Kindly note that I am new to MATLAB)

谢谢

推荐答案

太棒了!哎哟!让我就跳进去打扰您,然后再继续这条路!

Ouch! OUCH! Let me just jump right in there and interrupt you before you continue down this path!

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

I know you're not a programmer, but at some point in life (apparently, this is yours!), you have to face the facts and become one, however momentarily. So know that programming is not really a science, it's an art, a craftsmanship if you will, and one that is all too easy to get wrong. Know also that there have been millions upon millions of programmers before you, who paved the way for you and found out which methods work best, and which methods lead to certain disaster.

我将描述代码中存在的确定的道路"中的六个.

I will describe six of these "roads-to-certain-doom" that are present in your code.

第一global的用法. 不要使用全局变量! 当然,它们适用于小型,简单的事情,但是更好,更易于管理,更持久,更健壮,更少容易出错的数据传递方式是手动.根据经验,创建所有顶级函数时应尽可能少地依赖于其他函数/变量.这是因为全局变量在程序状态和函数输出之间建立了紧密的联系,这使得重现任何错误(即使不是不可能的)变得困难,并且调试(这实际上是任何程序员花费大部分时间进行的工作)的噩梦.另外,除了运行该功能以外的任何功能都可以更改它们,因此

First on the list, is the use of global. DON'T USE GLOBAL VARIABLES!! Sure, they are all-right for small, simple things, but the better, much more manageable, more durable, robust, much less error-prone way of passing data around is to do it manually. As a rule of thumb, create all top-level functions with as little dependencies to other functions/variables as possible. This is because global variables create a tight coupling between a program's state and a function's output, which makes reproducing any errors hard, if not impossible, and debugging (which is actually what any programmer spends most of his/her time on) a complete nightmare. Also, any function other than the one running can change them, so that

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'};  

有时工作,而有时失败.可能发生的更坏情况的一个示例:

will sometimes work, and sometimes fail. An example of something worse that can happen:

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

不会有错误,没有警告,什么也没有,但是您的结果仍然是垃圾.并且随着您的函数变得越来越大(通常它们会),该错误变得越来越越来越难.花几天的时间来发现这种错误并不罕见.

There will be no error, no warning, nothing, but your results will still be garbage. And as your functions grow larger (and they WILL, usually), this error gets harder and harder and harder to find. It's not uncommon to spend a good few days on finding this sort of mistake.

在代码中,您还可以在循环内更改全局变量ab.这意味着任何使用ab的函数/脚本(在完成后称为 的情况下)都将看到a=10b=10.现在,假设您在这些循环内调用函数 ,该函数会更改a的值. a的值在下一次迭代a循环时将是什么?假设您也得到了错误的结果.您将如何找到该错误?

In your code, you also change the global variables a and b inside the loops. This means that any function/script that uses a and b, that gets called after this one completes, will see a=10 and b=10. Now suppose you call a function inside those loops, that changes the value of a. What will the value of a be on the next iteration of the a-loop? Suppose also you get erroneous results. How would you go about finding that error?

由于明显的原因,这样的代码通常称为意大利面条代码".也许它会起作用,并且很容易编写代码,但是最终,它总是会极大地降低您的速度(更不用说继承您代码的人了).

Code like this is usually called "spaghetti code", for obvious reasons. Perhaps it will work, and is easy to code, but in the end it will always slow you down tremendously (not to mention the one who inherits your code).

一种防止大多数情况发生的更好方法是将数据收集到较大的容器中,并明确地传递它们.假设我们对数据a-l使用struct:

A much better approach that prevents most of this is to collect data in larger containers, and explicitly pass them around. Say we use a struct for the data a-l:

data = struct(...
    'a', a,...
    'b', b,...
    'c', c,...
    'd', d,...
    'e', e,...
    'f', f,...
    'g', g,...
    'h', h,...
    'l', l);

这样你就可以说

result = myFunction(data);

访问myFunction内部的数据的方式如下:data.a获取a的值,或data.f获取f的值,依此类推.在myFunction 中说data.k = 5;不会改变 result或传递给该函数的原始data -您已经破坏了紧密的连接并避免了上述所有问题.

Accessing data inside myFunction goes like this: data.a to get the value for a, or data.f for the value of f, etc. Saying data.k = 5; in myFunction will not change the result, or the original data passed to the function -- you have broken the tight coupling and prevented all the aforementioned problems.

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

Type help struct or help cell in the Matlab command window to learn about these sorts of generic containers.

第二使用的是变量名称l.这有点愚蠢,我对此很简短:不要这样做:)与大多数人(甚至是某些程序员)所相信的相反,您只写一次代码行一次,但您却阅读数百次,甚至数千次.最佳做法是使阅读尽可能容易,而不是写作. l看起来像1,不是吗?与k=m vs k=1相比,错误k=1 vs k=l更难发现.

Second on the list is using the variable name l. It's somewhat silly, and I can be short about this: don't do that :) Contrary to what most people (and even some programmers) believe, you write a line of code only once, but you read it hundreds, if not thousands of times. The best practice is to make the reading as easy as possible, not the writing. The l just looks like the 1, doesn't it? The bug k=1 vs k=l is simply harder to spot than k=m vs k=1.

第三是关键字transpose.这有点冗长,不是吗?在数学中,您将使用A T ,它比一直写完整的定义要容易得多:

Third on the list is the keyword transpose. It's kinda verbose, isn't it? In math, you would use AT, which is much easier on the eyes than writing the full definition all of the time:

B = {A ij ➝A ji ∀i< m⋏j< n

B = { Aij ➝ Aji ∀ i < m ⋏ j < n

您通常只说B = A T .在Matlab中也一样.矩阵的transpose可以像这样完成:

you normally just say B = AT. Same in Matlab. The transpose of a matrix can be accomplished like so:

Actrans = A' ; % conjugate transpose
Atrans  = A.'; % regular transpose

这会将您的代码减少到更少的冗长

which reduces your code to the much less verbose

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.';

列表中的

第四是等式K==M.就目前而言,KM矩阵.表达式K==M的计算方式为 element-wise ,其原因在您的编程生涯后期将变得显而易见:)这意味着K==M仍将是一个矩阵,其大小与KM,如果KM中的对应元素不相等,则包含0,如果这些元素相等,则包含1.那么,if语句对这样的矩阵有什么作用?在Matlab中,每当 first 元素为true时,它将为true(在我看来,它应该抛出一个错误,但是很好).

Fourth on the list is the equality K==M. As it stands here, K and M are matrices. The expression K==M is evaluated element-wise, for reasons that will become obvious later in your programming career :) This means that K==M will be again a matrix, the same size as K and M, containing 0 if corresponding elements in K and M are not equal, and 1 if these elements are equal. So, what will an if-statement do with such a matrix? In Matlab, it will be true whenever the first element is true (in my opinion, it should throw an error, but oh well).

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

This is obviously not what you want. what I think you want is that all elements in both matrices are equal. It's best you use this:

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

其中,(:)表示在比较之前应将矩阵KM扩展为列向量.这是因为all()在单个维度上起作用,因此all(K==M) still 用作矩阵(向量,实际上,但是对于同一事物的特殊情况,这是一个不同的名称).请注意,我不使用相等(==),而是检查它们的差是否小于某个微小值(eps).这是因为在浮点算术(所有计算机都使用)中,乘法和平方根之类的运算通常会遭受舍入误差和逼近/插值误差之类的影响. 平等是一个非常苛刻的要求,在数学上应该满足的大多数情况下,很难评估为true.您可以通过将两者的差异与与舍入误差(eps)相关的微小值进行比较来防止这种无法检测到相等性的情况.

where the (:)-notation means that the matrix K and M should be expanded to column-vectors prior to the comparison. This is because all() works down a single dimension, so all(K==M) would still be a matrix (vector, actually, but that's a different name for a special case of the same thing). Notice that I don't use equality (==), but rather check whether their difference is smaller than some tiny value (eps). This is because in floating-point arithmetic (which all computers use), operations like multiplication and square root usually suffer from things like round-off error and approximation/interpolation error. An equality is a very tough demand, too tough to evaluate to true in most cases where it mathematically speaking should. You can prevent this failure to detect the equality by comparing the difference of the two to a tiny value that's related to round-off error (eps).

第五是打印内容的方式. print语句本身将向系统的默认打印机发送一个图形,您知道,如果今天想合作的话,那台机器会吐出上面有墨水的纸张:)现在,我想您正在尝试在屏幕上显示.像开始显示事物那样进行操作并不是最好的方法:未命名,非结构化值的列表将得到十倍的结果:

Fifth on the list is the way you print things. The print statement, by itself, will send a figure to the system's default printer, you know, that moody machine that spits out paper with ink on it if it feels like cooperating today :) Now, I assume you were trying to display things on the screen. Doing it like the way you set out to display things is not the best way: you'll get a dozen times this list of unnamed, unstructured values:

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'
...

仅看到值出现会使阅读和解释正在发生的事情变得很乏味.最好使用更具描述性的内容:

Seeing only the values appear makes reading and interpreting what's going on rather tedious. Better use something more descriptive:

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

选项1只会显示

a = 
    1
b = 
    1
etc.

,它至少还显示变量的名称和值.选项2是更好的选择:

which at least also shows the variable's name alongside its value. Option 2 is the nicer one:

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

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

etc.

(顺便说一句,循环中的值a,b,d,e,f 从不改变,所以为什么要首先显示它们?)

(As an aside, the values a,b,d,e,f never change in the loops, so why would you want to show them in the first place?)

第六(也是最后一个!)是Matlab特有的:for-循环. Matlab是一种基于矩阵的解释型语言.它的矩阵性质仅意味着每个变量本质上都是一个矩阵.解释意味着您的代码不会被计算机处理器直接看到,它们将必须经过一系列解释和翻译,才能计算出任何内容.这个硬币有两个方面:

Sixth (and last!) on the list, is one that is specific to Matlab: for-loops. Matlab is an interpreted, matrix-based language. Its matrix nature simply means that every variable is in essence, a matrix. Interpreted means that your code will not directly be seen by the computer's processor, it will have to go through a series of interpretations and translations before anything gets calculated. This coin has two sides:

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

从性能上来说,for循环在Matlab中是臭名昭著的,它可以使操作缓慢进行.进入Matlab的方式通常是 vectorized 代码,例如,利用所有变量都是矩阵的事实,并对它们使用矩阵/张量运算而不是循环.这在大多数编程语言中都不是很常见的方法(您会在不习惯它的程序员中看到很多强大的,强烈的抵抗力),但是在数学上下文中,这是很有意义的.在使用for循环之前,请始终尝试将矩阵/张量运算作为第一道攻击线(Matlab有很多 ,请注意!).

In light of performance, the for-loop is notorious in Matlab for bringing operations to a crawl. The way to go in Matlab is usually vectorized code, e.g., use the fact that all variables are matrices, and use matrix/tensor operations on them instead of loops. This is not a very common approach in most programming languages (and you'll see a lot of strong, heated resistance to it in programmers not accustomed to it), but in a mathematical context it makes a whole lot of sense. Always try to use matrix/tensor operations as a first line of attack (and Matlab has a lot of them, mind you!) before resorting to for-loops.

所以,那是您的代码出了什么问题:)哦,是的,正如安德烈亚斯·汉高(Andreas Hangauer)所提到的那样,将引用al的语句放进去,所有需要重新-循规蹈矩地计算,在循环内,您会没事的.

So, that's what's wrong with your code :) Oh yeah, and as Andreas Hangauer already mentioned, place the statements referring to a through l, and all that needs to be re-calculated accordinly, inside the loop, and you'll be fine.

这篇关于此MATLAB代码有什么问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆