是否使用" 1"而不是" 0"?

时间:2013-03-10 23:56:06

标签: c++ .net biginteger bit-shift twos-complement

我通过将一些C ++函数移植到.NET的BigInteger来独立研究位移。我注意到当我移动BigInteger时,虚空被填充了。

我认为这与以二元赞美形式存储的负数有关。

BigInteger num = -126;
compactBitsRepresentation = (uint)(int)(num << 16);

以下是班次之后发生的事情(最重要的第一位)

10000010 will be shifted 16
11111111100000100000000000000000 was shifted 16

我是否总是期望类似的位移操作以这种方式运行?这是否与OpenSSL等“bigNumber”的不同语言和实现一致?

3 个答案:

答案 0 :(得分:1)

来自BigInteger.LeftShift operator docs

  

与使用整数基元的按位左移操作不同   LeftShift方法保留原始BigInteger值的符号。

所以.NET保证你看到的行为。

我对bignum库并不熟悉,但OpenSSL的BIGNUM BN_lshift()函数的文档说:

  

BN_lshift()向左移位n位并将结果放在r(“r = a * 2 ^ n”)中。 BN_lshift1()将左移一个并将结果放在r(“r = 2 * a”)中。

由于操作是以2的幂乘法定义的,如果将得到的BIGNUM转换为2的补码数(我不知道BIGNUM如何在内部表示数字),那么你会看到类似于.NET的行为

如果其他bignum库表现相似,我不会感到惊讶,但如果你想依赖行为,你真的需要检查文档。但是,由于移位非常类似于乘法或除以2的幂,所以通过使用适当的乘法或除法而不是移位,您可能可以获得“便携”行为。那么你需要确保的是你可以将转换转换为二进制补码表示(这个问题实际上与转换操作的行为无关)。

答案 1 :(得分:1)

  

我是否总是期望类似的位移操作以这种方式运行?

如果所讨论的数字格式使用两个补码来表示负数(并且很多都是),则应该这样做。要形成数字的二进制补码,可以反转所有位并添加一个,例如:

23 is represented as 00010111
-23 is represented as 11101001 (that is, 11101000 + 1)

此外,当您将类型转换为更大的类型时,该值通常是符号扩展的,即最左边的位扩展为较大类型的额外位。这保留了数字的符号。

所以是的,数字表示通常用数字值“填充”为1是很常见的。

答案 2 :(得分:0)

首先将<100> 10000010更改为更大的宽度。在这种情况下,4个字节:

10000010 --> 11111111 11111111 11111111 10000010

左边是1,因为数字是负数。

现在左移只是从右边插入0并从左边掷出位:

11111111 11111111 11111111 10000010 << 16 -->
11111111 10000010 00000000 00000000