逻辑数组与向量化
matlab有两个基本类型的数据类型:数字型与字符型。数字型数据包括数字,字符型数据包含字符。除这两个数据类型之外,还有第三类数据类:逻辑型。
“逻辑”数据类型在matlab中并不真实存在。其实,它是带特定逻辑属性标准数字型数据类型。逻辑型数组通过所有的关系运算符和逻辑运算符创建。它们区别于数字型的是在调用whos命令时,(logical)会出现在类型的后面。
例如,考虑下面的语句
a = [1 2 3; 4 5 6; 7 8 9]; b = a > 5;
这些语句将会产生两个数组a和b。a将会产生一个数组file:///C:/Users/lx/AppData/Local/Temp/msohtmlclip1/01/clip_image002.gif,b将会产生一个特殊的含有逻辑属性file:///C:/Users/lx/AppData/Local/Temp/msohtmlclip1/01/clip_image004.gif。当调用whos命令时,结果如下。注意b后面的(logical)修饰符。
>> whos Name Size Bytes Class a 3x3 72 double array b 3x3 9 logical array Grand total is 18 elements using 81bytes
我们还可以用logical函数给一个数组加上一个逻辑属性。例如,语句c=logical(a),将会把a值赋于c,从而使c带有一定的逻辑性:
一个数组的逻辑属性可以通任何的数学运算去除。例如,如果我们在c数组加0,数组的值不会改变,而它的逻辑属性将会消失
>> c=b+0 c = 0 0 0 0 0 1 1 1 1 >> whos Name Size Bytes Class a 3x3 72 double array b 3x3 9 logical array c 3x3 72 double array Grand total is 27 elements using 153bytes
逻辑数组的重要性
逻辑数组有一个重要的属性——它在算术运算中能提供一个屏蔽(mask)。
屏蔽(mask)是指一个数组,它从另一个数组选择所需的元素参与运算。指定的运算只在选择的元素上执行,而不执行原有的元素。
例如,假设数组a和b的定义如上节所示。那么语句a(b)=sqrt(a(b))会计算a中相应的元素的平方根,相应的元素是指与b数组中的非零元素相对应的数组a中的元素。其他元素保持不变。
>> a(b)=sqrt(a(b)) a = 1.0000 2.0000 3.0000 4.0000 5.0000 2.4495 2.6458 2.8284 3.0000
对于一个数组的子集快速而简单,而不用循环和选择结构。
下面的语句,是用循环结构和选择结构计算上述问题。
for ii = 1:size(a,1) for jj = 1:size(a,2) if a(ii,jj) > 5 a(ii,jj)=sqrt(a(ii,jj)); end end end b = a > 5; a(b) = sqrt(a(b));
例4.6
用逻辑数数组进行屏蔽运算为了比较循环结构,选择结构与应用逻辑数组运算的快慢,我们进行下面两个计算,并对它进行计时。
1.创建一个含10000个元素的数组,其值依次为1到10000之间的整数。用for循环和if结构计算大于5000的元素的平方根。
2.创建一个含10000个元素的数组,其值依次为1到10000之间的整数。用逻辑数组计算大于5000的元素的平方根。
答案:
这个程序必须创建一个含10000个元素的数组,其值依次为1到10000之间的整数。用两种不同的方法计算出大于5000的元素的平方根。
比较两种方法运行速度的matlab程序如下所示:
% Script file:logical1.m % % Purpose: % This program calculates the time required to % calculate the square roots of all elements in % array a whose value exceeds 5000. This is done % in two differents ways: % 1.Using a for loop and if construct. % 2.Using a logical array. % % Record of revisions: % Date Programmer Description of change % ==== ================ ============================== % 06/01/02 S. J. Chapman Original code % % Define variables: % a --Array ofinput values % b --Logicalarray to serve as a mask % ii,jj --Loop index % average1 --Average timefor calculation 1 % average2 --Average timefor calculation 2 % maxcount --Number oftimes to loop calculation % month --Month (mm) % year --Year (yyyy) % % Perform calculation using loops andbranches maxcount = 1; % One repetition tic; % Start timer for jj = 1:maxcount a = 1:10000; %Declare arraya for ii = 1:10000 if a(ii) > 5000 a(ii) = sqrt(a(ii)); end end end average1 = (toc)/maxcount;%Calculateaverage time % % Perform calculation using logicalarrays. maxcount = 10; %One repetition tic; %Start timer for jj = 1:maxcount a = 1:10000; %Declare array a b = a > 5000; %Create mask a(b) = sqrt(a(b)); %Take squareroot end average2 = (toc)/maxcount; %Calculate average time % % Display result fprintf('Loop/if approach = %8.4f\n',average1); fprintf('Logical array approach = %8.4f\n',average2);
这个程序在cpu为奔腾III(主频为733mhz)的计算机运行得到结果如下
>> logical1 Loop /if approach = 0.1200 Logical array approach = 0.0060
正如我们看到的,用逻辑数组方法速度是另一种方法的20倍。
好的编程习惯
如果用可能的话,可用逻辑函数选择数组中的元素。如果逻辑数组进行运算,要比循环快得多。
|