高效的bithifting一个int数组?

时间:2010-05-05 14:04:55

标签: c arrays bit-manipulation bit-shift

要在同一页面上,我们假设sizeof(int)= 4且sizeof(long)= 8.

给定一个整数数组,逻辑上将数组移位到左侧或右侧的有效方法是什么?

我正在考虑一个辅助变量,例如long,它将计算第一对元素(索引0和1)的bitshift并设置第一个元素(0)。以这种方式继续,元素(索引1和2)的bitshift将是计算机,然后将设置索引1。

我认为这实际上是一种相当有效的方法,但也有缺点。我不能比特位移大于32位。我认为使用多个辅助变量会起作用,但我想到的是沿线的某个地方进行递归。

3 个答案:

答案 0 :(得分:8)

无需使用long作为中间人。如果你向左移动,从最高顺序int开始,向右移动最低顺序。在修改之前从相邻元素中添加进位。

void ShiftLeftByOne(int * arr, int len)
{
    int i;
    for (i = 0;  i < len - 1;  ++i)
    {
        arr[i] = (arr[i] << 1) | ((arr[i+1] >> 31) & 1);
    }
    arr[len-1] = arr[len-1] << 1;
}

这种技术可以扩展到超过1位的移位。如果你的位数超过32位,你将位数mod 32移位,然后在数组中进一步移动结果。例如,要向左移位33位,代码看起来几乎相同:

void ShiftLeftBy33(int * arr, int len)
{
    int i;
    for (i = 0;  i < len - 2;  ++i)
    {
        arr[i] = (arr[i+1] << 1) | ((arr[i+2] >> 31) & 1);
    }
    arr[len-2] = arr[len-1] << 1;
    arr[len-1] = 0;
}

答案 1 :(得分:1)

查看BigInteger implementation in Java,它在内部将数据存储为字节数组。具体来说,你可以看看函数leftShift()。语法与C中的相同,因此编写像这样的一对函数并不太难。还要考虑到,当涉及到位移时,你可以在C中使用非中心类型。这意味着在Java中安全地移位数据而不用弄乱符号你通常需要更大的类型来保存数据(即移位的int)短暂的,长期的转移,...)

答案 2 :(得分:1)

对于其他任何人来说,对于任意数量的位和任何类型的数组,这是更通用的版本<{3}}:

/* This function shifts an array of byte of size len by shft number of
bits to the left. Assumes array is big endian. */

#define ARR_TYPE uint8_t

void ShiftLeft(ARR_TYPE * arr_out, ARR_TYPE * arr_in, int arr_len, int shft)
{
    const int int_n_bits = sizeof(ARR_TYPE) * 8;
    int msb_shifts = shft % int_n_bits;
    int lsb_shifts = int_n_bits - msb_shifts;
    int byte_shft = shft / int_n_bits;
    int last_byt = arr_len - byte_shft - 1;
    for (int i = 0;  i < arr_len;  i++){
        if (i <= last_byt){
            int msb_idx = i + byte_shft;
            arr_out[i] = arr_in[msb_idx] << msb_shifts;
            if (i != last_byt)
                arr_out[i] |= arr_in[msb_idx + 1] >> lsb_shifts;
        }
        else arr_out[i] = 0;
    }
}