matlab 预分配具有未分配元素的逻辑数组(非真或假)

6ljaweal  于 2022-11-15  发布在  Matlab
关注(0)|答案(1)|浏览(194)

我正在寻找在MATLAB中预分配逻辑数组而无需在预分配时指定TRUE或FALSE的最有效方法。
在预分配(例如,1×5数值数组)时,我可以使用nan(1,5)。在我看来,这比使用zeros(1,5)要好,因为我可以很容易地区分哪些槽已经填满了数据,哪些槽还没有填满。如果使用zeros()解决方案,则很难知道是否有任何0是故意使用的0,或者只是阵列中未填满的插槽。
我知道我可以使用true(1,5)false(1,5)预分配逻辑阵列。这些问题类似于数字示例中的zeros()的使用;无法知道空位是否已填满。
我知道这个问题的一种解决方案是将数组视为数字,并使用nan(1,5)进行预分配,然后在所有插槽都填满后才转换为逻辑数组。但这给我的印象是效率低下。
有没有什么聪明的方法可以在MatLab中预先分配一个逻辑数组,并对该数组的实际内容保持不可知,直到它准备好被填充?

5t7ly7z5

5t7ly7z51#

简短的回答是否定的,逻辑数组的要点是每个元素占用一个字节,并且该实现只能存储两种状态(TRUE=1或FALSE=0)。您可能会认为逻辑运算只需要一个位,但实际上they need 8 bits (a byte)是为了避免影响性能。
如果内存是一个问题,您可以使用single数组而不是double数组,从64位数字转移到32位数字,并且仍然能够存储NaN。然后,您可以在需要的时候强制转换为logical(假设到那时您还没有NAN,否则它将出错)。
如果在减少内存的同时跟踪某个值是否被赋值真的很重要,那么您可以拥有与第一个逻辑数组同时更新的第二个逻辑数组,并且简单地存储是否曾经赋值。然后,这可以用来检查赋值后是否还有任何缺省值。现在我们已经从32位单逻辑下降到两个8位逻辑,这比一个逻辑差,但仍然是为了NaN而使用浮点数的效率的两倍。显然,赋值操作现在所需的时间是使用单个逻辑数组的两倍,我不知道它们与浮点赋值相比如何。
在滑雪道之外,您可以创建自己的类来执行此任务跟踪,并显示逻辑数组,就好像它能够存储NAN一样。我们并不推荐这样做,但我已经编写了以下代码来完成思维实验。注意您最初要求的是“最有效的方法”,就执行时间而言,这肯定不会像逻辑数组的本机实现那样高效。

classdef nanBool
    properties
        assigned % Tracks whether element of "value" was ever assigned
        value    % Tracks boolean array
    end
    methods 
        function obj = nanBool(varargin)
            % Constructor: initialise main and tracking arrays to false
            % handles same inputs as using "false()" normally
            obj.value = false(varargin{:});
            obj.assigned = false(size(obj.value));        
        end
        function b = subsref(obj,S)
            % Override the indexing operator so that indexing works like it
            % would for a logical array unless accessing object properties
            if strcmp(S.type,'.')
                b = obj.(S.subs);
            else
                b = builtin('subsref',obj.value,S);            
            end
        end
        function obj = subsasgn(obj,S,B)
            % Override the assignement operator so that the value array is
            % updated when normal array indexing is used. In sync, update
            % the assigned state for the corresponding elements
            obj.value = builtin('subsasgn',obj.value,S,B);
            obj.assigned = builtin('subsasgn',obj.assigned,S,true(size(B)));
        end    
        function disp(obj)
            % Override the disp function so printing to the command window
            % renders NaN for elements which haven't been assigned
            a = double(obj.value);
            a(~obj.assigned) = NaN;
            disp(a);
        end
    end    
end

测试用例:

>> a = nanBool(3,1)

a = 
   NaN
   NaN
   NaN

>> a(2) = true

a = 
   NaN
     1
   NaN

>> a(3) = false

a = 
   NaN
     1
     0

>> a(:) = true

a = 
     1
     1
     1

>> whos a
  Name      Size            Bytes  Class      Attributes

  a         1x1                 6  nanBool       

>> b = false(3,1); whos b
  Name      Size            Bytes  Class      Attributes

  b         3x1                 3  logical

注意:whos测试显示此自定义类与两个大小相同的逻辑数组具有相同的内存占用。它还显示报告的大小不正确,这表明我们还必须覆盖自定义类中的size函数,我相信还有很多其他类似的边缘情况需要处理。
您可以检查是否有任何“逻辑NAN”(未赋值)具有类似的内容,或者向类中添加一个执行此操作的函数:

fullyAssigned = all(a.assigned);

在21b和更高版本中,您可以对定制类执行一些更受控制的索引覆盖,而不是subsrefsubsasgn,但我不能测试这一点:
https://uk.mathworks.com/help/matlab/customize-object-indexing.html

相关问题