给定要解释为位字符串的 MATLAB uint32,计算字符串中有多少非零位的有效且简洁的方法是什么?
我有一个可行的、幼稚的方法来循环这些位,但这对我的需要来说太慢了。(使用 std::bitset count() 的 C++ 实现几乎立即运行)。
我发现了一个非常不错的页面,列出了各种位计数技术,但我希望有一种简单的 MATLAB 式方法。
http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive
更新#1
刚刚实现了 Brian Kernighan 算法如下:
w = 0;
while ( bits > 0 )
bits = bitand( bits, bits-1 );
w = w + 1;
end
性能仍然很糟糕,仅计算 4096^2 权重计算需要超过 10 秒。我的 C++ 代码使用 std::bitset 中的 count() 可以在亚秒时间内完成。
更新#2
这是迄今为止我尝试过的技术的运行时间表。当我得到更多的想法/建议时,我会更新它。
矢量化 Scheiner 算法 => 2.243511 秒 矢量化 Naive bitget 循环 => 7.553345 秒 Kernighan 算法 => 17.154692 秒 长度(查找(bitget(val,1:32)))=> 67.368278 秒 nnz(bitget(val, 1:32)) => 349.620259 秒 Justin Scheiner 的算法,展开循环 => 370.846031 秒 Justin Scheiner 的算法 => 398.786320 秒 天真的 bitget 循环 => 456.016731 秒 sum(dec2bin(val) == '1') => 1069.851993 秒
评论:MATLAB 中的 dec2bin() 函数似乎实现得很差。它运行非常缓慢。
评论:“Naive bitget loop”算法实现如下:
w=0;
for i=1:32
if bitget( val, i ) == 1
w = w + 1;
end
end
评论: Scheiner 算法的循环展开版本如下所示:
function w=computeWeight( val )
w = val;
w = bitand(bitshift(w, -1), uint32(1431655765)) + ...
bitand(w, uint32(1431655765));
w = bitand(bitshift(w, -2), uint32(858993459)) + ...
bitand(w, uint32(858993459));
w = bitand(bitshift(w, -4), uint32(252645135)) + ...
bitand(w, uint32(252645135));
w = bitand(bitshift(w, -8), uint32(16711935)) + ...
bitand(w, uint32(16711935));
w = bitand(bitshift(w, -16), uint32(65535)) + ...
bitand(w, uint32(65535));