我在想这个世界是有效的,但事实并非如此:
int a = -500; a = a << 1; a = (unsigned int)a >> 1; //printf("%d",a) gives me "2147483148"
我的想法是左移会移除最左边的符号位,所以右移它作为无符号整数将保证它是一个逻辑移位而不是算术.为什么这不正确?
也:
int a = -500; a = a << 1; //printf("%d",a) gives me "-1000"
user1952500.. 7
TL; DR:最简单的方法是使用abs
函数
.答案的其余部分涉及在计算机上表示负数.
负整数(几乎总是)以2的补码形式表示.(见下面的注释)
获得数字否定的方法是:
取整数的二进制表示(包括数据类型的前导零,除了将用作符号位的MSB).
取上述数字的1的补码.
添加1
到1的补码.
前缀符号位.
以身500
作为例,
采取的二进制表示500
:_000 0001 1111 0100
(_
为符号位的占位符).
取1的补码/倒数: _111 1110 0000 1011
添加1
到1的补码:_111 1110 0000 1011 + 1 = _111 1110 0000 1100
.2147483148
当您将符号位替换为零时,这与您获得的相同.
前缀0
显示正数和1
负数:1111 1110 0000 1100
.(这与2147483148
上面不同.你得到上述价值的原因是因为你获得了MSB).
反转标志是一个类似的过程.如果您使用16位或32位数字导致您看到的大值,那么您将得到领先的数字.在每种情况下LSB应该相同.
注意:有些机器具有1的补码表示,但它们是少数.2的补码通常是首选,因为0
具有相同的表示,即,-0
并且0
在2的补码表示法中表示为全零.
TL; DR:最简单的方法是使用abs
函数
.答案的其余部分涉及在计算机上表示负数.
负整数(几乎总是)以2的补码形式表示.(见下面的注释)
获得数字否定的方法是:
取整数的二进制表示(包括数据类型的前导零,除了将用作符号位的MSB).
取上述数字的1的补码.
添加1
到1的补码.
前缀符号位.
以身500
作为例,
采取的二进制表示500
:_000 0001 1111 0100
(_
为符号位的占位符).
取1的补码/倒数: _111 1110 0000 1011
添加1
到1的补码:_111 1110 0000 1011 + 1 = _111 1110 0000 1100
.2147483148
当您将符号位替换为零时,这与您获得的相同.
前缀0
显示正数和1
负数:1111 1110 0000 1100
.(这与2147483148
上面不同.你得到上述价值的原因是因为你获得了MSB).
反转标志是一个类似的过程.如果您使用16位或32位数字导致您看到的大值,那么您将得到领先的数字.在每种情况下LSB应该相同.
注意:有些机器具有1的补码表示,但它们是少数.2的补码通常是首选,因为0
具有相同的表示,即,-0
并且0
在2的补码表示法中表示为全零.