左移的负数*总是*用"1"而不是"0"填充吗?
Are negative numbers that are left shifted *always* filled in with "1" instead of "0"?
我正在通过将一些c++函数移植到。net的BigInteger来独立研究位移位。我注意到,当我移动BigInteger时,空白被1填充。
我认为这与负数以双互补形式存储有关。
BigInteger num = -126;
compactBitsRepresentation = (uint)(int)(num << 16);
下面是移位后的结果(最有效位优先)
10000010 will be shifted 16
11111111100000100000000000000000 was shifted 16
我应该总是期望类似的位移操作以这种方式进行吗?这是否与OpenSSL等"bignnumber"的不同语言和实现一致?
来自BigInteger.LeftShift
操作符文档:
与整型元的按位左移操作不同LeftShift方法保留原来BigInteger值的符号。
所以。net保证了你看到的行为。
我对bignum库不太熟悉,但是OpenSSL的bignum BN_lshift() '函数的文档说:
BN_lshift()
将a左移n位,并将结果放入r ("r=a*2^n")。BN_lshift1()
将a向左移动1,并将结果放入r("r=2*a")。
由于该操作是根据2的乘方定义的,如果将结果BIGNUM转换为2的补数(我不知道BIGNUM内部如何表示数字),那么您将看到与。net类似的行为。
如果其他bigum库有类似的行为,我不会感到惊讶,但如果你想依赖于这种行为,你真的需要检查文档。然而,由于移位非常类似于乘法或除以2的幂,您可能可以通过使用适当的乘法或除法而不是移位来获得"可移植"的行为。然后,您需要确保的是可以将其转换为二进制补码表示(这是一个真正独立于移位操作行为的问题)。我应该总是期望类似的位移操作以这种方式进行吗?
如果有问题的数字格式使用2的补码来表示负数(很多都是这样),那么应该这样做。要形成一个数字的二补数,你要把所有的位反转并加一,所以例如:
23 is represented as 00010111
-23 is represented as 11101001 (that is, 11101000 + 1)
此外,当您将类型转换为较大类型时,该值通常是符号扩展的,即最左边的位扩展为较大类型中的额外位。保留数字的符号。
所以,是的,数值表示用1"填充"是很常见的。
10000010首先改为更大的宽度。在本例中,为4字节:
10000010 --> 11111111 11111111 11111111 10000010
左边是1,因为数字是负数
现在左移只是从右边插入0,从左边插入位:
11111111 11111111 11111111 10000010 << 16 -->
11111111 10000010 00000000 00000000
相关文章:
- 在c++中用vector填充一个简单的动态数组
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- QueryWorkingSet总是返回false
- 如何使用用户输入在C++中正确填充2D数组
- 无论条件是否为true,if总是在c++中执行
- 如何找到大小'x'数组是否完全填充,在C++?
- C++A*算法并不总是在路径中具有目标节点
- 为什么(-1)%vector::size()总是返回0
- Cuda C++:设备上的Malloc类,并用来自主机的数据填充它
- xmake总是报告:错误:无法获取cxx的程序,为什么
- 通过for循环使用用户输入填充列表
- 类型总是使用其大小存储在内存中吗
- 使用std::istream::peek()总是安全的吗
- OpenMP:并行更新数组总是需要减少数组吗
- 在我的代码中,获得最大的Pair Wise产品C++和输出并不总是正确的
- 根据用户输入用字母填充矢量,并将"开始"和"结束"放在四肢
- OpenGL 和 GLM 矩阵无法正确扩展,总是按比例缩小
- 对于C++,方括号中的标题必须总是在引号中的标题之上吗
- 为什么无符号的 int 右移总是用"1"填充
- 左移的负数*总是*用"1"而不是"0"填充吗?