当没有...位移操作符时位移

时间:2012-04-30 03:49:18

标签: vbscript bit-manipulation bit-shift

我必须实现校验和(CRC16 CCITT)来验证文件的内容。 由于<<<<<<<<<<<<和>>运营商和网上提供的许多例子。

事情是......我的校验和计算必须在VBScript中实现。

我使用这种语言的经验几乎是空的,但根据我的理解,在VBScript中没有提供任何可以进行位移的东西。因此,我依靠乘法和除以2。除了负值之外,它的效果很好。

我运行了一些测试,我相信VBScript用两个补码来处理它的16位整数。

Q1:有人可以确认一下(VBScript中的两个补码)吗?我没有从MSDN网站上找到任何准确的信息。

Q2:当负数用二进制补码编码时,是否可以通过简单的数学运算进行位移(左右)?

非常感谢,我真的想避免使用整数作为'1'和'0'的数组或从VBScript调用一些java / c应用程序的kludge。

编辑感谢您的帮助,请在下面找到我在VBScript中右移的实现:

Function rightShift(value,bits)
    Dim res

    res = 65535 AND value

    If value>=0 Then
       res = res \ (2^bits)
    Else If value=-1 Then
             res = rightShift(res + 32768, bits - 1)
         Else
             res = rightShift(value \ 2 + 32768, bits - 1)
         End If
    End If

    rightShift = res AND 65535
End Function 

注意上面的代码:值有时超过16位,因此我必须屏蔽未使用的位以避免溢出(AND 65535)。

3 个答案:

答案 0 :(得分:5)

在二进制补码算法中,除以2向右移动时出现负值的唯一影响:将发生预期的右移,但它也会在最高有效位(MSB)中引入新的1位)位置“保持值为负” - 除非原始值为-1,在这种情况下所有位都变为0.因此要纠正此问题,请尝试以下伪代码:

rightshift(x) {
    if x >= 0 return x / 2;
    if x < -1 return x / 2 - MINVAL;    # Strip out sign bit
    # x must be -1, i.e. "all bits on"
    return x - MINVAL;
}

MINVAL应该是其表示仅包含MSB on和所有其他位off的值,对于16位是-32768。 (之所以这么命名是因为它将是使用二进制补码的最负面可表示的数字。)有趣的是,添加MINVAL的效果与在上面的伪代码中减去它一样,因为在二进制补码算法中,x - y = x + NOT(y) + 1MINVAL == NOT(MINVAL) + 1

左移使用乘法2对负数进行左移,就像对正数进行左移一样。

答案 1 :(得分:0)

这不是答案,而是评论。 @j_random_hacker给出的答案对我有用。但是在执行像C#这样的整数除法的语言中(假设你不能出于任何原因使用内置右移运算符),当x不均匀时,需要将其向上舍入。

static int MINVAL = (int) -0x80000000;
    static int ShiftRight(int n,int bits)
    {
        //if (n >= 0) return n / (int)Math.Pow(2, bits);
        //double temp = n / Math.Pow(2, bits);
        //int r  = (int) Math.Floor(temp);
        //return r;
        if (n >= 0) return n / 2;
        if (n < -1) return (int)Math.Round(n / (double)2, MidpointRounding.AwayFromZero) - MINVAL;//+ (n%2==0?0:-1);    // Strip out sign bit
        // x must be -1, i.e. "all bits on"
        return n - MINVAL;
    }

现在是的,C#有一个内置的移位操作符,所以这只是教育目的。

答案 2 :(得分:-1)

这很慢,试试这个。以下适用于值&gt; = 0但会 抛出数组下标超出位移的范围&gt; 14位,代码是:

dim ShiftArray
ShiftArray = Array(1, 2, 4, 8, 16, 32, 64, 128, 256, 512,
1024,2048,4096, 8192, 16384)

' example usage
dim num
num = 17
num = num * ShiftArray(2) ' left shift 2 bits
num = num / ShiftArray(3) ' right shift 3 bits

乘以左移的位数乘以。分为右移。 该数组适用于16位整数。

对于32位整数,数组将跳出超出边界的数组下标以进行位移&gt; 30,是:

dim ShiftArray
ShiftArray = Array(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,   
2048,4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288,
1048576, 2097152, 4194304, 8388608, 16777216, 33554432,
67108864, 134217728, 268435456,  536870912, 1073741824)