[英]C# Weird division issue
我有一种int和一种uint类型:
int tempA = 0xbc000669;
uint tempB = 0xbc000669;
当我做
tempA /0x2000
,想向右移动13,它给我0xfffde001
而
tempB / 0x2000
,也想向右移动13,它给了我正确的答案: 0x0005e000
有人知道为什么签名后我得到一个错误的答案吗? 我没想到分裂会溢出吗? 谢谢
在声明中
tempA / 0x2000
编译器会看到int类型的变量和数字文字值。 由于对int类型的除法需要两个int类型的操作数,因此值0x2000也会自动转换为int。 该语句评估为
(int)0xbc000669 / (int)0x2000
这是-1140849047 / 8192等于-139263
十六进制的-139263是FFFDE001(至少在32位值上)
实际上0xbc000669
不能包含在一个int
,更确切的说它代表一个negative integer
。 我们知道一个int
使用第32nd bit
作为sign bit
。 而0cbc000669
有最显著半字节为0xb
其等于1011
- >的32nd bit
是1
,实际是一个负整数。 所以:
int tempA = 0xbc000669;
将使tempA
等于-1140849047
,将此数字右移13个二进制数字将返回获得的准确结果: 0xfffde001
。
如果您像这样将tempB
声明为uint
:
uint tempB = 0xbc000669;
它可以完全包含在uint
因为uint
不使用第32nd bit
作为符号位。 实际数字是一个positive integer
,其值是3154118249
,将该值右移13个二进制数将得到准确的结果为0x5e000
从规范中关于整数除法的内容来看:
除法将结果舍入为零,结果的绝对值是最大可能的整数,该整数小于两个操作数的商的绝对值。 当两个操作数具有相同的符号时,结果为零或正;而当两个操作数具有相反的符号时,结果为零或负。
如果我正确地解释了该文本,则会导致以下情况:在第一个示例中,带符号的int值设置了符号位; 第二个数字(0x2000)为正,因此结果为零或负。
解释此问题的最佳方法是显示位如何工作。 Wikipedia上有关签名数字表示的文章对此进行了很好的介绍。 您将要阅读关于二进制补码的部分。
我认为期望是人们希望-1和1的二进制数相同,但-1的符号位为1。 不是这种情况。 1,例如
0000 0000 0000 0000 0000 0000 0000 0001
-1是
1111 1111 1111 1111 1111 1111 1111 1111
人们直觉上认为-1实际上是-127:
-127 == 1000 0000 0000 0000 0000 0000 0000 0001
现在,让我们看看您得到的答案。 在有符号除法中,当您向右移动时,实际上实际上是将数字的左侧填充1并加1。这就是您在结果中看到的结果。
0xFFFDE001 = 1111 1111 1111 1101 1110 0000 0000 0001
0x0005E000 = 0000 0000 0000 0101 1110 0000 0000 0000
您会注意到,它们都是一样的,除了最上面的(来自已签名部门的)左边有13 1的填充,末尾有1的填充。
对于带符号整数,要记住的重要一点是,二进制补码会更改位的顺序,因此,除符号位外,-50不具有与+50相同的位模式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.