罗兰在MATLAB的艺术

把想法变成MATLAB

请注意

罗兰在MATLAB的艺术已经存档,不会被更新。

值语义的价值

我很高兴欢迎回来戴夫Foti检查一些值语义的方式在MATLAB工作对象和如何最小化数据拷贝。

我知道你们中的一些人可能远程学习的孩子在家里现在,我想分享一个MATLAB对象我用来帮助我的儿子练习乘法。虽然可以构建这个应用程序,我想让纸测试这个例子的目的是做一个测试,可以打印出来。你们中的一些人可能熟悉MATLAB处理对象或者使用其他语言对象总是引用的地方。我想用我的示例类指出的一些原因以MATLAB处理或引用语义往往是不必要的。

内容

处理和价值观

首先,我认为一个句柄是一个对象,该对象可以访问一些数据不是对象本身的一部分,但可以从对象。当我通过这个对象,我不通过实际数据,但只是一个ID提供手段来达到这一数据。这意味着当我改变所有的数据对象,我可能该ID传递给许多功能。许多变量在不同的地方现在可以访问相同的数据,看看这些变化。是非常有意义代表现实世界中的对象处理,因为你不能仅仅复制真实的对象。例如,如果我有一个培训对象,旨在追踪列车的位置,它看起来像这样:

classdef火车<处理属性数字的位置结束方法函数p =火车(数量、位置)p。数量=数量;p。位置=位置;结束结束结束

无论我有多少变量用于存储处理同样的火车,我总是看到相同的状态。

X =火车(5402“波士顿”);Y = X;%我们可以复制处理或ID,而不是火车本身Y。位置=“纽约”;X.Location
ans =“纽约”

我所说的一个值或值语义,是当我对象传递给一个函数的函数接收一份所有对象中包含的数据。同样的,当我将一个对象分配给一个新的变量,该变量得到的所有数据的副本,两个变量可以保存相同的数据,改变一个变量的数据的对象永远不会改变不同变量的数据。当数字是最常见的形式的值,许多类型的对象可以受益于相同的值语义。以我的算术测试为例,它只是一个集合的参数和算术问题。

测试=相乘(“NumProblems”,50岁,“马克斯”,10)
测试=相乘的属性:NumProblems: 50马克斯:10 X:[50×1双]Y:[50×1双]Z:[50×1双]OpSymbol:“×”

现在,如果我想要一个新的测试,都是一样的除了从1到12 1到10,我可以指定一个新变量测试然后修改而不改变测试

test12 =测试;test12.Max= 12; test12 = drawProblems(test12);%重新创建和绘制问题

我原来的测试是没有改变:

测试
测试=相乘的属性:NumProblems: 50马克斯:10 X:[50×1双]Y:[50×1双]Z:[50×1双]OpSymbol:“×”

语义复制在MATLAB是有效的

有时人们担心这些复制的对象将导致使用大量内存。重要的是要意识到MATLAB优化副本在许多方面使其有效。当一个对象从一个变量复制到另一个,MATLAB只是记录这个事实,但实际上没有数据复制。这两个变量实际上是引用同一个对象,但它知道它与多个变量。这并不重要,直到其中一个变量是用来修改对象。即便如此,MATLAB的浅拷贝对象这意味着任何矩阵内仍没有被改变的对象共享。当一个属性被修改,只有该属性的数据复制,不是属性的数据没有修改。如果我们再看看上面的例子:

test12 =测试;test12.Max= 12;

test12.Max改变,没有复制的问题,因为这些数组仍然可以在对象之间共享。当我们重绘问题,只有这样的新数组创建新的问题。与这些简单的例子,你不会注意到差别,但是当对象存储非常大的数组,有效副本做一个真正的区别。

值语义清楚输入和输出

MATLAB的特点之一,我一直欣赏的是你可以看看一个函数调用,轻松地告诉什么是输入和输出,即使一个变量是一个输入和一个输出。一些语言和系统使用的输入输出,你必须阅读功能文档或输入参数注释,如“在”,“从”和“/”来了解如何使用的参数。在MATLAB中,输入在右边,左边的输出是在/和参数出现在左边和右边。当使用一个变量在左边和右边的函数调用,MATLAB通常可以避免复制即使修改变量的函数。让我们看看前几行ArithmeticTest drawProblems函数:

dbtypeArithmeticTest.m45:50
45函数t = drawProblems (t, withAnswers) 47 46参数t 48 withAnswers(1, 1)逻辑= false;49结束50 t = genProblems (t);

在45行,我们可以看到t既是输入和输出。有时这意味着MATLAB可以修改t到位没有复制,但是只有在调用函数使用相同的输入和输出变量。我们可以看到一个这样的例子在50行调用不同的方法。甚至通过这些多层次的函数调用,t是可能从来没有真正复制,因为它可能MATLAB可以告诉它不需要多一份保护值语义。

下面你会发现完整的程序清单供参考:

我想听到你创建任何新值的例子类型在MATLAB。请描述或你想分享的链接在这里

附录:代码文件

classdefArithmeticTest% ArithmeticTest算术测试的抽象基类属性%的问题在测试NumProblems (1,1) {mustBeReal, mustBeInteger} = 35;%限制操作数的值马克斯(1,1){mustBeReal, mustBeInteger} = 20;结束属性(SetAccess =保护)X Y Z OpSymbol结束方法(抽象)t = genProblems (t)结束方法函数t = ArithmeticTest (params)%分配所有的属性的名称值对%被构造对象。s =字符串(字段名(params)”) t。(s) =参数。(s);结束结束结束方法(访问=保护)函数op = getSymbol (t, k)如果isscalar (t.OpSymbol) op = t.OpSymbol;其他的op = t.OpSymbol (k);结束结束结束方法% drawProblems画一个图,可以印刷的问题% drawProblems (t, true)将打印的问题的答案%填写。函数t = drawProblems (t, withAnswers)参数t withAnswers(1,1)逻辑= false;结束t = genProblems (t);如果(t。NumProblems < = 48)约= 6;kN = 8;字形大小= 20;axPos = [0 0 7 10];elseif(t。NumProblems < = 80)约= 8;kN = 10;字形大小= 12;axPos = (0.55 0 8.5 - 10.4);其他的约= 10;kN = 10;字形大小= 12;axPos = (0.55 0 8.5 - 10.4);结束图(f =“单位”,“英寸”,“位置”[3 0 8.5 11]);一个=轴(“父”f“单位”,“英寸”,“位置”,axPos);一个。可见=“关闭”;一个。XLim =[0约+ 1];一个。YLim = [0 kN];n = 1;j = 1:约k = 1: kN如果(n > t.NumProblems)打破;结束x = t.X ((j - 1) * kN + k);y = t.Y ((j - 1) * kN + k);如果(x < 99) & & (< 99) dx = 2;dy = 2;其他的dx = 3;dy = 3;结束文本(j - tx1 =。8 k。3sprintf (“%”+ dx +“d \ n % s %”+ dy +“d”,x, t.getSymbol (n), y));tx1。字体名=“明星控制台”;tx1。字形大小=字形大小;tx1。翻译=“没有”;如果(x < 99) & & (y < 99) underlineTxt =“___”;其他的underlineTxt =“____”;结束文本(j - tx2 =。8 k -。44,underlineTxt); tx2.FontName =“快递新”;并。字形大小=字形大小;并。翻译=“没有”;如果(withAnswers) tx3 = (j -文本。8 k -。7,sprintf (“%”+ dx +“d”,t.Z ((j - 1) *约+ k)));tx3。字体名=“快递新”;tx3。字形大小=字形大小;tx3。翻译=“没有”;结束n = n + 1;结束如果(n > t.NumProblems)打破;结束结束结束结束结束classdef乘< ArithmeticTest%为乘法乘测试问题方法函数t =相乘(params)参数参数。乘结束t@ArithmeticTest (params);t。OpSymbol = char (215);% Unicode代码点00 d7t = drawProblems (t);结束函数t = genProblems (t)提高(“洗牌”);%开始繁殖的所有组合%的数量从1…t.Max。A1 = 1: t.Max;A2 = 1: t.Max;X = 0 (t。马克斯^ 2,1);Y = 0 (t。马克斯^ 2,1);k = 1: t.Maxj = 1: t。最大X ((k - 1) * t.Max + j, 1) = A1 (k);Y ((k - 1) * t.Max + j, 1) = A2 (j);结束结束%减少涉及10 - 1的简单问题。idx =找到(X = = 10);X (idx (1:5)) = [];Y (idx (1:5)) = [];idx =找到(Y = = 10);X (idx (1:5)) = [];Y (idx (1:5)) = [];idx =找到(X = = 1);X (idx (1:5)) = [];Y (idx (1:5)) = [];idx =找到(Y = = 1); X(idx(1:5)) = []; Y(idx(1:5)) = [];%随机排列的问题,并确保我们有%不够的问题。numProbs =元素个数(X);numSets =装天花板(t.NumProblems / numProbs);t。X = 0 (t。NumProblems, 1);t。Y = 0 (t。NumProblems, 1);如果numSets > 1k = 1: numSets-1 idx = randperm (numProbs numProbs);t.X ((k - 1) * numProbs + 1: k * numProbs) = X (idx);t.Y ((k - 1) * numProbs + 1: k * numProbs) = Y (idx);结束其他的k = 0;结束idx = randperm (numProbs numProbs);t.X (k * numProbs + 1:结束)= X (idx (1: t.NumProblems-k * numProbs));t.Y (k * numProbs + 1:结束)= Y (idx (1: t.NumProblems-k * numProbs));%计算产品下载188bet金宝搏t。Z = t。X。* t.Y;结束结束结束




发表与MATLAB®R2020a


评论

留下你的评论,请点击在这里MathWorks账户登录或创建一个新的。