C#奇怪的分裂问题

时间:2013-09-25 18:30:44

标签: c# math

我有一个int和一个uint类型:

int tempA = 0xbc000669;
uint tempB = 0xbc000669;

当我做的时候

tempA /0x2000,想要向右移动13,它会给我0xfffde001

,而

tempB / 0x2000,想要向右移动13,它给了我正确答案:0x0005e000

任何人都知道为什么有签名的部门,我得到一个错误的答案?我不认为师可能会溢出?感谢

4 个答案:

答案 0 :(得分:4)

声明

tempA / 0x2000

编译器会看到int类型的变量和数字文字值。由于int类型的除法需要两个int类型的操作数,因此值0x2000也会自动转换为int。该陈述评估为

(int)0xbc000669 / (int)0x2000

是 -1140849047 / 8192并等于-139263

-139263(十六进制)是FFFDE001(至少32位值)

答案 1 :(得分:1)

0xbc000669实际上{strong}中的不能包含,更准确地说它代表int。我们知道negative integer使用int作为32nd bit。虽然sign bit最重要的半字节为0cbc000669,但等于0xb - > 101132nd bit,实际整数为负数。所以:

1

会使int tempA = 0xbc000669; 等于tempA,右移这个数字的13位二进制数字将返回您得到的确切结果:-1140849047

如果您将0xfffde001声明为tempB,请执行以下操作:

uint

它可以完全包含在uint tempB = 0xbc000669; 中,因为uint不使用uint作为符号位。实际数字为32nd bit,其值为positive integer,右移此值为13位二进制数字将为您提供3154118249

的确切结果

答案 2 :(得分:0)

关于整数除法的规范中的模糊:

  

除法将结果舍入为零,结果的绝对值是小于两个操作数的商的绝对值的最大可能整数。当两个操作数具有相同的符号时,结果为零或正,当两个操作数具有相反的符号时,结果为零或负。

如果我正确地解释了该文本,则会导致这种情况:在第一个示例中,signed int值设置了符号位;第二个数字(0x2000)为正数,因此结果为零或负数。

答案 3 :(得分:0)

解释这个的最好方法是展示这些位是如何工作的。 The 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

现在让我们来看看你得到的答案。在签名的分区中,当你向右移动时,你实际上最终用1s填充数字的左侧,并添加1.这正是你对结果的看法。

0xFFFDE001 = 1111 1111 1111 1101 1110 0000 0000 0001
0x0005E000 = 0000 0000 0000 0101 1110 0000 0000 0000

正如你会注意到的那样,它们都是相同的,除了顶部的一个(来自你签名的部门)左边有13个填充,最后加1个。

使用有符号整数要记住的重要一点是,两个补码会改变位的排序,因此,除了符号位,-50与+50的位模式不同。