二进制数向量的高效位改组
Efficient bit shuffling of vector of binary numbers
我记录了包含位序列向量的数据,我想有效地重新排列这些数据。数据向量中的一个值可能如下所示:
bit0, bit1, bit2, ... bit7
我想将这个位序列重新排列成这个顺序:
bit0, bit7, bit1, bit6, bit2, bit5, bit3, bit4
如果我只有一个值,这将通过以下方式很好地工作:
sum(uint32(bitset(0,1:8,bitget(uint32(X), [1 8 2 7 3 6 4 5]))))
不幸的是,bitset 和 bitget 无法处理位序列向量。由于我有一个相当大的数据集,我对有效的解决方案很感兴趣。
任何帮助将不胜感激,谢谢!
我不知道我是否会把问题弄错,但这不是可以通过索引包裹到 cellfun
中来解决吗?
%// example data
BIN{1} = dec2bin(84,8)
BIN{2} = dec2bin(42,8)
%// pattern and reordering
pattern = [1 8 2 7 3 6 4 5];
output = cellfun(@(x) x(pattern), BIN, 'uni', 0)
或者您输入的格式和期望的输出是什么?
BIN =
'01010100' '00101010'
output =
'00100110' '00011001'
dec2bin
和bin2dec
可以处理向量,你可以一次输入所有数字并置换矩阵:
input=1:23;
pattern = [1 8 2 7 3 6 4 5];
bit=dec2bin(input(:),numel(pattern));
if size(bit,2)>numel(pattern)
warning('input numbers to large for pattern, leading bits will be cut off')
end
output=bin2dec(bit(:,pattern));
如果可用,我会使用 de2bi
和 bi2de
。
最有效的方法可能是像您在问题中所做的那样使用 bitget
和 bitset
,尽管您只需要一个 8 位整数。假设你有一个 uint8
数组 X
来描述你记录的数据(对于下面的例子,X = uint8([169;5])
,没有特别的原因。我们可以通过创建一个有用的匿名函数来检查这些位:
>> dispbits = @(W) arrayfun(@(X) disp(bitget(X,1:8)),W)
>> dispbits =
@(W)arrayfun(@(X)disp(bitget(X,1:8)),W)
>> dispbits(X)
1 0 0 1 0 1 0 1
1 0 1 0 0 0 0 0
并假设您有一些模式 pattern
,您希望根据该模式对存储在该整数向量中的位进行重新排序:
>> pattern
pattern =
1 8 2 7 3 6 4 5
您可以使用 arrayfun
和 find
根据 pattern
对位重新排序:
Y = arrayfun(@(X) uint8(sum(bitset(uint8(0),find(bitget(X,pattern))))), X)
Y =
99
17
我们得到了有效存储在 8 位整数向量中的所需答案:
>> class(Y)
ans =
uint8
>> dispbits(Y)
1 1 0 0 0 1 1 0
1 0 0 0 1 0 0 0
我记录了包含位序列向量的数据,我想有效地重新排列这些数据。数据向量中的一个值可能如下所示:
bit0, bit1, bit2, ... bit7
我想将这个位序列重新排列成这个顺序:
bit0, bit7, bit1, bit6, bit2, bit5, bit3, bit4
如果我只有一个值,这将通过以下方式很好地工作:
sum(uint32(bitset(0,1:8,bitget(uint32(X), [1 8 2 7 3 6 4 5]))))
不幸的是,bitset 和 bitget 无法处理位序列向量。由于我有一个相当大的数据集,我对有效的解决方案很感兴趣。
任何帮助将不胜感激,谢谢!
我不知道我是否会把问题弄错,但这不是可以通过索引包裹到 cellfun
中来解决吗?
%// example data
BIN{1} = dec2bin(84,8)
BIN{2} = dec2bin(42,8)
%// pattern and reordering
pattern = [1 8 2 7 3 6 4 5];
output = cellfun(@(x) x(pattern), BIN, 'uni', 0)
或者您输入的格式和期望的输出是什么?
BIN =
'01010100' '00101010'
output =
'00100110' '00011001'
dec2bin
和bin2dec
可以处理向量,你可以一次输入所有数字并置换矩阵:
input=1:23;
pattern = [1 8 2 7 3 6 4 5];
bit=dec2bin(input(:),numel(pattern));
if size(bit,2)>numel(pattern)
warning('input numbers to large for pattern, leading bits will be cut off')
end
output=bin2dec(bit(:,pattern));
如果可用,我会使用 de2bi
和 bi2de
。
最有效的方法可能是像您在问题中所做的那样使用 bitget
和 bitset
,尽管您只需要一个 8 位整数。假设你有一个 uint8
数组 X
来描述你记录的数据(对于下面的例子,X = uint8([169;5])
,没有特别的原因。我们可以通过创建一个有用的匿名函数来检查这些位:
>> dispbits = @(W) arrayfun(@(X) disp(bitget(X,1:8)),W)
>> dispbits =
@(W)arrayfun(@(X)disp(bitget(X,1:8)),W)
>> dispbits(X)
1 0 0 1 0 1 0 1
1 0 1 0 0 0 0 0
并假设您有一些模式 pattern
,您希望根据该模式对存储在该整数向量中的位进行重新排序:
>> pattern
pattern =
1 8 2 7 3 6 4 5
您可以使用 arrayfun
和 find
根据 pattern
对位重新排序:
Y = arrayfun(@(X) uint8(sum(bitset(uint8(0),find(bitget(X,pattern))))), X)
Y =
99
17
我们得到了有效存储在 8 位整数向量中的所需答案:
>> class(Y)
ans =
uint8
>> dispbits(Y)
1 1 0 0 0 1 1 0
1 0 0 0 1 0 0 0