Reputation: 695
I have one int and one uint type:
int tempA = 0xbc000669;
uint tempB = 0xbc000669;
when I do
tempA /0x2000
, wanting to shift to the right by 13, it gives me 0xfffde001
while
tempB / 0x2000
, wanting also to shift to the right by 13, it gives me the correct answer: 0x0005e000
anybody knows why with a signed division, I get a false answer? I didn't think division could overflow? Thanks
Upvotes: 0
Views: 222
Reputation: 7793
In the statement
tempA / 0x2000
the compiler sees a variable of type int and a numeric literal value. Since division on type int requires two operands of type int, the value 0x2000 is automatically cast to int as well. The statement evaluates to
(int)0xbc000669 / (int)0x2000
which is -1140849047 / 8192 and equals to -139263
-139263 in hex is FFFDE001 (on 32 bit values at least)
Upvotes: 4
Reputation: 63377
0xbc000669
in fact can't be contained in an int
, more exactly it will represent a negative integer
. We know that an int
uses the 32nd bit
as the 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. 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
.
if you declare your tempB
as uint
like this:
uint tempB = 0xbc000669;
it can be contained totally in a uint
because uint
doesn't use the 32nd bit
as the sign 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
Upvotes: 1
Reputation: 1396
The best way to explain this is to show how the bits work out. The Wikipedia article on signed number representation covers it well. 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. This is not the case. 1, for example, is
0000 0000 0000 0000 0000 0000 0000 0001
And -1 is
1111 1111 1111 1111 1111 1111 1111 1111
What people would intuitively think is -1 is actually -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.
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.
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.
Upvotes: 0
Reputation: 10184
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; the second number (0x2000) is positive, thus the result is either zero or negative.
Upvotes: 0