按照从最高有效到最低有效 C# 的顺序从 short[] 中分离位

Posted

技术标签:

【中文标题】按照从最高有效到最低有效 C# 的顺序从 short[] 中分离位【英文标题】:Separate bits from short[] in order of most to least significant C# 【发布时间】:2021-06-30 13:26:38 【问题描述】:

我想将包含在 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++ 中执行此操作可能会更好,但我希望完全管理程序。

【问题讨论】:

我在第一关就掉了下来:我不知道你是怎么把0101 0101 0101 0101变成0000 1111 0000 1111 这是每个半字节的第一位,然后是每个半字节的第二位,依此类推。 这里的另一个小问题...短是 16 位,因此永远不能有 5 个“半字节”。 所以要反转它,您将当前位移动到(TotalNibbles - 当前位迭代计数器 - currentnibble)或者我错过了什么?我也不明白为什么你在输入法中硬编码位置而不是计数。 我知道这只是一个例子,说明如果元素的数量不是类型中位数的倍数,任务将如何变得更加复杂。 【参考方案1】:

我不想回答自己的问题,但我刚刚发现了 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];

【讨论】:

以上是关于按照从最高有效到最低有效 C# 的顺序从 short[] 中分离位的主要内容,如果未能解决你的问题,请参考以下文章

字节序

学习《深入理解计算机系统(第三版)》第二章总结

大端序和小端序,最高有效位和最低有效位

什么是大小端

20145326蔡馨熠《信息安全系统设计基础》第三周学习总结

最高有效位基数排序如何比最低有效位基数排序更有效?