首页 > 解决方案 > 按从最高有效到最低有效 C# 的顺序从 short[] 中分离位

问题描述

我想将包含在 byte[] 中的 short[] 的位分开,以便每个 short 的最高有效位排列在一个连续的块中(数组?行?),然后是每个 short 的下一位,依此类推。这是位布局将如何变化的精简示例:

0101010101010101 0101010101010101
would become
0011001100110011 0011001100110011
or with 3 it would look like
0101010101010101 0101010101010101 0101010101010101
which would become
0001110001110001 1100011100011100 0111000111000111

我把它放在一个代码块中以保留换行符。

如果我可以单独处理每个位,这将很容易,但我必须使用按位运算符,这使得它非常困难。

忽略数组中元素的数量不是基本类型位长度的倍数的可能性,在这种情况下为 16,我想出了这个:

fixed(byte* inptr = sourcearray){ //the shorts in a byte[]
    fixed(byte* outptr = destination){//the output byte[]
        var insamples = (short*)inptr;
        var outsamples = (ushort*)outptr;
        var mask = (ushort)0b1000000000000000;
        for(int i = 0, j = 0; i < numsamples; ++i, j += 16){
            if(j >= numsamples){
                j = 0;
                mask >>= 1;
            }
            outsamples[i] = (ushort)((insamples[j] & mask) | ((insamples[j + 1] & mask) >> 1) | ((insamples[j + 2] & mask) >> 2) | ((insamples[j + 3] & mask) >> 3) |
                                    ((insamples[j + 4] & mask) >> 4) | ((insamples[j + 5] & mask) >> 5) | ((insamples[j + 6] & mask) >> 6) | ((insamples[j + 7] & mask) >> 7) |
                                    ((insamples[j + 8] & mask) >> 8) | ((insamples[j + 9] & mask) >> 9) | ((insamples[j + 10] & mask) >> 10) | ((insamples[j + 11] & mask) >> 11) |
                                    ((insamples[j + 12] & mask) >> 12) | ((insamples[j + 13] & mask) >> 13) | ((insamples[j + 14] & mask) >> 14) | ((insamples[j + 15] & mask) >> 15));
        }
    }
}

我正在使用的数组有 480 个短裤(960 字节)长,我很确定它可以满足我的要求,但是我无法编写与将数组恢复到原始状态相反的函数,所以到目前为止,我没有任何意义,我需要它合理优化以最小化所需的处理,但它伤害了我的大脑。

在 C++ 中执行此操作可能会更好,但我想完全管理程序。

标签: c#arraysbit-manipulationshort

解决方案


我不想回答我自己的问题,但我刚刚发现了 System.Collections.BitArray 类,它允许我单独处理位,并在几分钟内将操作中的代码替换为:

for(int i = 0, j = 0, k = 0; i < inbits.Length; ++i, j += 16){
    if(j >= inbits.Length) j = ++k;
    _outbitsout[i] = inbits[j];
}

并扭转该操作:

var stride = inbits.Length/16;
for(int i = 0, j = 0, k = 0; i < inbits.Length; ++i, j += stride){
    if(j >= inbits.Length) j = ++k;
    _outbitsin[i] = inbits[j];
}

推荐阅读