我该怎么做才能缩短这段代码?

时间:2016-11-07 21:17:47

标签: arrays matlab performance plot matlab-figure

我想为更多k计算此函数,例如k = 6,7,8...等:

f(k,a)=( - 1) k a - ( - 1) k (kπ/ t) 2 < / p>

然后我想为所有k绘制它。我只想要更短的形式。我试图将k写为向量,但这不起作用。这是我的代码:

clear all
close all
clc
w = linspace(-1,10,5000);
t = 2*pi;

k = 0;
a0 = w.^2;
b0 = (-1).^k.*a0-((-1).^k).*(k*pi/t).^2;
b = a0*0;
k1 = 1;
a01 = w.^2;
b01 = (-1).^k1.*a01-((-1).^k1).*(k1*pi/t).^2;

k2 = 2;
a02 = w.^2;
b02 = (-1).^k2.*a02-((-1).^k2).*(k2*pi/t).^2;

k3 = 3;
a03 = w.^2;
b03 = (-1).^k3.*a03-((-1).^k3).*(k3*pi/t).^2;

k4 = 4;
a04 = w.^2;
b04 = (-1).^k4.*a04-((-1).^k4).*(k4*pi/t).^2;

k5 = 5;
a05 = w.^2;
b05 = (-1).^k5.*a05-((-1).^k5).*(k5*pi/t).^2;

plot(a0,b,'.')
hold on
plot(a0,b0,'.')
hold on
grid on
plot(a01,b01,'.')

2 个答案:

答案 0 :(得分:3)

tl; dr - 这是紧凑和矢量化方式:

t = 2*pi;
myfun = @(k,a) (-1).^k.*a-((-1).^k).*(k*pi/t).^2;
k = 0:30; % here you can add as many k's you like
w = linspace(-1,10,5000).^2.';
b0 = zeros(size(w));
B = bsxfun(myfun,k,w);
plot(w,[b0 B],'.')
grid on

结果:

enter image description here

<强>说明:

您的代码演示了如何不使用变量。如果a01==a02==a03...那么您可以对所有这些a使用a,则无需定义所有这些b0。对于函数b01w = linspace(-1,10,5000); t = 2*pi; b_fun = @(k,a) (-1).^k.*a-((-1).^k).*(k*pi/t).^2; a = w.^2; k = 0; b0 = b_fun(k,a); b = a*0; k1 = 1; b01 = b_fun(k1,a); k2=2; b02 = b_fun(k2,a); k3=3; b03 = b_fun(k3,a); k4 = 4; b04 = b_fun(k4,a); k5 = 5; b05 = b_fun(k5,a); 等也是如此,你可以定义一个匿名函数(最短的函数类型),然后反复调用它。如果你只是做了这两件事,你上面的代码(没有绘图)变成:

t

哪个更短,更易读。请注意,我们在函数之前定义a,因此它是根据函数中的值计算的。

接下来,您可以使用singleton expansion在一个命令中(以矢量化方式)计算来自kk = 0:5 B = bsxfun(b_fun,k,a.'); 的元素的所有成对组合:< / p>

b_fun(k(i),a)

这会创建一个矩阵,其中每列都是bsxfun的结果值。 b_fun的第一个输入是任何元素二进制操作,就像我们的函数bsxfun一样。接下来总是有两个数组(其中一个可以是标量),第一个包含函数中第一个参数的所有值,第二个包含第二个参数。如果其中一个数组具有单个维度而另一个数据大于1,则k扩展较小的一个以适应较大的一个。在我们的例子中,a在行中是单例,k在列中是单例,因此结果为no。来自a的列和否。来自w = linspace(-1,10,5000); t = 2*pi; b_fun = @(k,a) (-1).^k.*a-((-1).^k).*(k*pi/t).^2; a = w.^2; k = 0:5; B = bsxfun(b_fun,k,a.'); b = a*0; 的行。

所以我们得到了:

w.^2

我们可以进一步删除一些重复的变量 - 使用a代替pi/t,并将常量0.5替换为b = zeros(size(w))。写a*0代替w = linspace(-1,10,5000).'; b_fun = @(k,a) (-1).^k.*a-((-1).^k).*(k*0.5).^2; k = 0:5; B = bsxfun(b_fun,k,w.^2); b = zeros(size(w));

也更清楚
plot

现在进行策划。 B可以在一个矩阵的列中显示几个系列的数据,并针对同一个变量显示所有数据,因此我们可以直接使用b,只需将其连接到plot(w.^2,[b B],'.')

        foreach (var item1 in new String []{ "John", "J", "john", "j"})
        {
            foreach (var item2 in new String[] { "John", "J", "john", "j" })
            {
                if (item1!=item2)
                {
                    Console.WriteLine("({0,-12}{1,6},{2,6}", item1+","+item2+"):", 
                        string.CompareOrdinal(item1,item2), string.Compare(item1,item2));
                }
            }
        }

答案 1 :(得分:0)

您可以从编程中的函数定义中受益。这样的事情可以做到:

function main
w=linspace(-1,10,5000);
t=2*pi;

figure;hold on
for k=0:5
    [a,b] = getNext(k,w,t);
    plot(a,b,'.');
end

function [a,b] = getNext(k,w,t)
a = w.^2;
b = (-1).^k.*a-((-1).^k).*(k*pi/t).^2;
end
end 

请记住,这不是唯一的解决方案。其他获得类似结果的方法也是可能的。

<强>更新 使用arrayfun的内置for循环是这样的:

w = linspace(-1,10,5000);
t = 2*pi;
a = w.^2;
K = [0 1 2 3 4 5 6 7];
S = arrayfun(@(k)((-1).^k.*a-((-1).^k).*(k*pi/t).^2),K,'UniformOutput',false);
figure;hold on
for ii=1:numel(K)
    plot(a,S{ii},'.');
end