我在想这个世界是有效的,但事实并非如此:
int a = -500;
a = a << 1;
//printf("%d",a) gives me "-1000"
我的想法是左移会移除最左边的符号位,所以右移它作为无符号整数将保证它是一个逻辑移位而不是算术。为什么这不正确?
此外:
func sendRequest () {
print("fire now----------------------------------------------")
let parameters: Parameters = ["user": "001", "name": "josh"]
print(parameters)
let a = Alamofire.request("http://120.77.252.96:8388/", method: .get, parameters: parameters, encoding: URLEncoding.default).validate(statusCode: 200..<500).responseJSON(completionHandler: {responds in
switch responds.result {
case .success(let value):
let json = JSON(value)
print("JSON: \(json)")
case .failure(let error):
print(error)
}}
)
print(a)
}
答案 0 :(得分:7)
TL; DR:最简单的方法是使用abs
中的<stdlib.h>
函数。答案的其余部分涉及在计算机上表示负数。
负整数(几乎总是)在2's complement form中表示。 (见下面的注释)
获得数字否定的方法是:
1
添加到1补码。以500
为例,
500
的二进制表示形式:_000 0001 1111 0100
(_
是符号位的占位符。)_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的补码表示法中表示为全零。
答案 1 :(得分:3)
左移负整数会调用未定义的行为,因此您无法执行此操作。如果您使用 a =(unsigned int)a&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; 1; 代码>。你得到500 =
0xFFFFFE0C
,左移1 = 0xFFFFFC18
。
a =(unsigned int)a&gt;&gt; 1;
确实保证了逻辑移位,因此你得到 0x7FFFFE0C
。这是小数2147483148。
但这是不必要的复杂。 更改符号位的最佳和最便携的方法是 a = -a
。任何其他代码或方法都值得怀疑。
如果你坚持做点蠢事,你也可以做类似
&#xA; &#xA; (int32_t)a&amp; 〜(1u&lt;&lt; 31)&#xA;
&#xA;&#xA; 这可以移植到32位系统,因为(int32_t)
保证两个补码,但 1u&lt;&lt; 31
假设32位 int
类型。
演示:
&#xA;&#xA; #include&lt; stdio.h&gt;&#xA; #include&lt; stdint.h&gt;&#xA;&#xA; int main(void)&#xA; {&#xA; int a = -500;&#xA; a =(unsigned int)a&lt;&lt; 1;&#XA; a =(unsigned int)a&gt;&gt; 1;&#XA; printf(“%。8X =%d \ n”,a,a);&#xA;&#xA; _Static_assert(sizeof(int)&gt; = 4,“Int必须至少为32位。”);&#xA; a = -500;&#xA; a =(int32_t)a&amp; 〜(1u <&lt; 31);&#xA; printf(“%。8X =%d \ n”,a,a);&#xA;&#xA;返回0;&#xA;}&#xA;
&#xA;
答案 2 :(得分:-1)
当您放入“另外”部分时,在第一次左移1位后,DOES会按预期反映-1000。
问题在于你的转换为unsigned int。如上所述,负数表示为2的补码,意味着符号由最左位(最高有效位)确定。当转换为unsigned int时,该值不再表示符号,但会增加int可以采用的最大值。
假设32位整数,MSB用于表示-2 ^ 31(= -2147483648),现在在无符号整数中表示正2147483648,增加2 * 2147483648 = 4294967296.将其添加到原始值 - 1000,你得到4294966296.右移将此除以2,你到达2147483148。
希望这可能会有所帮助:(来自Print an int in binary representation using C的修改后的打印功能)
void int2bin(int a, char *buffer, int buf_size) {
buffer += (buf_size - 1);
for (int i = buf_size-1; i >= 0; i--) {
*buffer-- = (a & 1) + '0';
a >>= 1;
}
}
int main() {
int test = -500;
int bufSize = sizeof(int)*8 + 1;
char buf[bufSize];
buf[bufSize-1] = '\0';
int2bin(test, buf, bufSize-1);
printf("%i (%u): %s\n", test, (unsigned int)test, buf);
//Prints: -500 (4294966796): 11111111111111111111111000001100
test = test << 1;
int2bin(test, buf, bufSize-1);
printf("%i (%u): %s\n", test, (unsigned int)test, buf);
//Prints: -1000 (4294966296): 11111111111111111111110000011000
test = 500;
int2bin(test, buf, bufSize-1);
printf("%i (%u): %s\n", test, (unsigned int)test, buf);
//Prints: 500 (500): 00000000000000000000000111110100
return 0;
}