c++ - 左移的负数是否*总是*用 "1"而不是 "0"填充?

标签 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”的不同语言和实现一致?

最佳答案

来自BigInteger.LeftShift operator docs :

Unlike the bitwise left-shift operation with integer primitives, the LeftShift method preserves the sign of the original BigInteger value.

因此 .NET 保证了您看到的行为。

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

BN_lshift() shifts a left by n bits and places the result in r ("r=a*2^n"). BN_lshift1() shifts a left by one and places the result in r ("r=2*a").

由于该运算是根据乘以 2 的幂来定义的,如果将生成的 BIGNUM 转换为二进制补码(我不知道 BIGNUM 在内部如何表示数字),那么您将看到与 .NET 类似的行为.

如果其他 bignum 库的行为类似,我不会感到惊讶,但如果您想依赖于该行为,您确实需要检查文档。但是,由于移位与乘以或除以 2 的幂非常相似,因此您可以通过使用适当的乘法或除法而不是移位来获得“可移植”的行为。然后您需要确保的是您可以转换为二进制补码表示(这是一个真正独立于移位操作行为的问题)。

关于c++ - 左移的负数是否*总是*用 "1"而不是 "0"填充?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15329215/

相关文章:

java - 如何纠正这个使用 BigInteger 的 java 代码?

c++ - 在着色器中动态变化

c++ - 使用成员创建数组时的不同 -Wsign-conversion 行为

c++ - 链接使用不同版本的 gcc 编译的库

c# - 事务管理使用TransactionScope()

C++使用链表、模板和栈设计一个大整数加减法的类

c# - 在 dotnet 核心中捕获 native 异常

c# - 在单元测试类中使用 CaSTLe Windsor

c# - 无法加载文件或程序集 'System.Net.Http'

typescript - 无法在 typescript 版本 3.1.6 中使用 BigInt。错误 TS2304 : Cannot find name 'BigInt'