我正在通过将一些 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/