简体   繁体   English

C#奇怪的部门问题

[英]C# Weird division issue

I have one int and one uint type: 我有一种int和一种uint类型:

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

when I do 当我做

tempA /0x2000 , wanting to shift to the right by 13, it gives me 0xfffde001 tempA /0x2000 ,想向右移动13,它给我0xfffde001

while

tempB / 0x2000 , wanting also to shift to the right by 13, it gives me the correct answer: 0x0005e000 tempB / 0x2000 ,也想向右移动13,它给了我正确的答案: 0x0005e000

anybody knows why with a signed division, I get a false answer? 有人知道为什么签名后我得到一个错误的答案吗? I didn't think division could overflow? 我没想到分裂会溢出吗? Thanks 谢谢

In the statement 在声明中

tempA / 0x2000

the compiler sees a variable of type int and a numeric literal value. 编译器会看到int类型的变量和数字文字值。 Since division on type int requires two operands of type int, the value 0x2000 is automatically cast to int as well. 由于对int类型的除法需要两个int类型的操作数,因此值0x2000也会自动转换为int。 The statement evaluates to 该语句评估为

(int)0xbc000669 / (int)0x2000

which is -1140849047 / 8192 and equals to -139263 这是-1140849047 / 8192等于-139263

-139263 in hex is FFFDE001 (on 32 bit values at least) 十六进制的-139263是FFFDE001(至少在32位值上)

0xbc000669 in fact can't be contained in an int , more exactly it will represent a negative integer . 实际上0xbc000669 不能包含在一个int ,更确切的说它代表一个negative integer We know that an int uses the 32nd bit as the sign bit . 我们知道一个int使用第32nd bit作为sign bit While 0cbc000669 has the most significant nibble as 0xb which is equal to 1011 -> the 32nd bit is 1 and the actual integer is negative. 0cbc000669有最显著半字节为0xb其等于1011 - >的32nd bit1 ,实际是一个负整数。 So: 所以:

int tempA = 0xbc000669;

will make tempA equal to -1140849047 , right-shifting this number 13 binary digits will return the exact result you get: 0xfffde001 . 将使tempA等于-1140849047 ,将此数字右移13个二进制数字将返回获得的准确结果: 0xfffde001

if you declare your tempB as uint like this: 如果您像这样将tempB声明为uint

uint tempB = 0xbc000669;

it can be contained totally in a uint because uint doesn't use the 32nd bit as the sign bit. 它可以完全包含在uint因为uint不使用第32nd bit作为符号位。 The actual number is a positive integer and its value is 3154118249 , right-shifting this value 13 binary digits will give you the exact result as 0x5e000 实际数字是一个positive integer ,其值是3154118249 ,将该值右移13个二进制数将得到准确的结果为0x5e000

From the blurb in the spec about integer division: 从规范中关于整数除法的内容来看:

The division rounds the result towards zero, and the absolute value of the result is the largest possible integer that is less than the absolute value of the quotient of the two operands. 除法将结果舍入为零,结果的绝对值是最大可能的整数,该整数小于两个操作数的商的绝对值。 The result is zero or positive when the two operands have the same sign and zero or negative when the two operands have opposite signs. 当两个操作数具有相同的符号时,结果为零或正;而当两个操作数具有相反的符号时,结果为零或负。

If I interpret that text correctly, it leads to this: In the first example, the signed int value has the sign bit set; 如果我正确地解释了该文本,则会导致以下情况:在第一个示例中,带符号的int值设置了符号位; the second number (0x2000) is positive, thus the result is either zero or negative. 第二个数字(0x2000)为正,因此结果为零或负。

The best way to explain this is to show how the bits work out. 解释此问题的最佳方法是显示位如何工作。 The Wikipedia article on signed number representation covers it well. Wikipedia上有关签名数字表示的文章对此进行了很好的介绍。 You'll want to read the the section on Two's complement. 您将要阅读关于二进制补码的部分。

The expectation, I think, is that people want the binary of -1 and 1 to be the same, with the exception that the sign bit is 1 for -1. 我认为期望是人们希望-1和1的二进制数相同,但-1的符号位为1。 This is not the case. 不是这种情况。 1, for example, is 1,例如

0000 0000 0000 0000 0000 0000 0000 0001

And -1 is -1是

1111 1111 1111 1111 1111 1111 1111 1111

What people would intuitively think is -1 is actually -127: 人们直觉上认为-1实际上是-127:

-127 == 1000 0000 0000 0000 0000 0000 0000 0001

So now let's look at the the answers you got. 现在,让我们看看您得到的答案。 In signed division, when you shift to the right, you actually end up padding the left side of your number with 1s, and adding 1. And that's exactly what you see with your results. 在有符号除法中,当您向右移动时,实际上实际上是将数字的左侧填充1并加1。这就是您在结果中看到的结果。

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

As you'll notice, they're both the same, except the top one(from your signed division) has 13 1's padded on the left, and an added 1 at the end. 您会注意到,它们都是一样的,除了最上面的(来自已签名部门的)左边有13 1的填充,末尾有1的填充。

The important thing to remember with signed integers is that two's complement changes the ordering of bits, so, excluding the sign bit, -50 does not have the same bit pattern as +50. 对于带符号整数,要记住的重要一点是,二进制补码会更改位的顺序,因此,除符号位外,-50不具有与+50相同的位模式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM