Why does a right shift on a signed integer causes an overflow? - bit-manipulation

Given any 8 bits negative integer (signed so between -1 and -128), a right shift in HLA causes an overflow and I don't understand why. If shifted once, it should basically divide the value by 2. This is true for positive numbers but obviously not for negative. Why? So for example if -10 is entered the result is +123.
Program cpy;
#include ("stdlib.hhf")
#include ("hla.hhf")
static
i:int8;
begin cpy;
stdout.put("Enter value to divide by 2: ");
stdin.geti8();
mov(al,i);
shr(1,i); //shift bits one position right
if(#o)then // if overlow
stdout.put("overflow");
endif;
end cpy;

Signed numbers are represented with their 2's complement in binary, plus a sign bit "on the left".
The 2's complement of 10 coded on 7 bits is 1110110, and the sign bit value for negative numbers is 1.
-10: 1111 0110
^
|
sign bit
Then you shift it to the right (when you right shift zeroes get added to the left):
-10 >> 1: 0111 1001
^
|
sign bit
Your sign bit is worth 0 (positive), and 1111011 is 123 in decimal.

Related

Significance of x & (-x) in 2's Complement?

Where '-' denotes negative x, and '&' denotes bitwise AND.
The numbers are in 8-bit 2's complement in a program and I can't seem to find the correlation between inputs and outputs.
8 & (-8) = 8
7 & (-7) = 1
97 & (-97) = 1
So possibly the significance is in the bit manipulation?
0000 1000 & (1111 1000) = 0000 1000
0000 0111 & (1111 1001) = 0000 0001
0110 0001 & (1001 1111) = 0000 0001
In each of the above cases the upper 4-bits always end up being 0's, but I cannot find a correlation between the inputs and what the lower 4-bits end up being.
Any ideas?
ANSWERED: Find the lowest set bit
To expound on the other answer, the two's complement is equal to the one's complement of a number plus 1. Let's look at how adding 1 to the one's complement of 8 goes.
8 -> 00001000 (bin) -> 11110111 (oc) -> 11111000 (tc)
Here, notice how the added 1 moves through the one's complement until it reaches the first 0, flipping that bit and the bits to the right of it. And, also note that the position of the first 0 in the one's complement is also the position of the first 1 in the original binary expression.
In x & (-x), the bits to the left of the first 1 in x will be 0 because they are all still flipped from taking the one's complement. Then, the bits to the right of the first 1 will also be 0 because they were 0 in x (else the first 1 would be earlier).
Thus, the output of x & (-x) will be the power of 2 corresponding to the location of the first 1 in x.
Two's complement is by definition, equals to the one's complement (all bits inversed) plus one.
If you were to do only the number & and its one complement, it would always give 0000 0000.
The key to understand the pattern lies here : if the + 1 operation changes other bits or only the last one. That is, if the number has a 1 at the end, and also if any reminder will propagate after the +1 addition.

Bitwise Relation between Shift Operator and One's Complement

I am new to Bitwise Operator,I found the following line in wikipedia of "Bitwise operator" -(https://en.wikipedia.org/wiki/Bitwise_operation )
If the binary number is treated as ones' complement, then the same
right-shift operation results in division by 2n and rounding toward
zero.
But not sure what it meant.Please help me to understand this.
It's about Right Shift Operation. Below answer is taken from my own blog:
Bitwise Operations
>> is a right shift bitwise operator which works exactly like left shift operator but it’s different in 2 aspects only.
If number is negative (most significant bit is 1) , it will fill gaps with 1 otherwise with 0
It shifts bits from right
7 >> 2
0000 0111 >> 2
0000 01 (See two 1’s from right have been shifted)
00 0000 01 (Added two 0’s, because number is positive)
0000 0001 = 1
So 7 >> 2 = 1
For negative number, it fills gaps with 1 instead of 0.
Remember 7 >> 2 = 1 and -7 >> 2 = -1.
It just preserves the sign, everything else remains same. If you closely observe right shift operator, you will find that it can be written as:
7 >> 2 => (7) / (2^2) => 7/4 => 1
This is what Wikipedia means, you can take right shift operator as:
NUMBER (7) / power (2, NUMBER_OF_TIMES (2)) and rounds it off

fixed point subtraction for two's complement data

I have some real data. For example +2 and -3. These data are represented in two's complement fixed point with 4 bit binary value where MSB represents the sign bit and number of fractional bit is zero.
So +2 = 0010
-3 = 1101
addition of this two numbers is (+2) + (-3)=-1
(0010)+(1101)=(1111)
But in case of subtraction (+2)-(-3) what should i do?
Is it needed to take the two's complement of 1101 (-3) again and add with 0010?
You can evaluate -(-3) in binary and than simply sums it with the other values.
With two's complement, evaluate the opposite of a number is pretty simple: just apply the NOT binary operation to every digits except for the less significant bit. The equation below uses the tilde to rapresent the NOT operation of a single bit and assumed to deal with integer rapresented by n bits (n = 4 in your example):
In your example (with an informal notation): -(-3) = -(1101) = 0011

Bit manipulation- for negative numbers

Let the size of integer i=-5 be 2 bytes. The signed bit value at the leftmost bit is '1'(which signifies that it is a negative number).
When i am trying to do a right shift operation, should i not expect the '1' at the 15th bit position to shift to 14th position? and give me a high but positive value?
What i tried:
int i=5;
i>>1 // giving me 2 (i understand this)
int i=-5
i>>1 // giving me -3 (mind=blown)
Right shifts of negative values are implementation-defined, [expr.shift]/3
The value of E1 >> E2 is E1 right-shifted E2 bit positions.
[..]. If E1 has a signed type and a negative value, the resulting
value is implementation-defined.
Most implementations use the so-called arithmetic shift though, which preserves and extends the sign-bit:
Shifting right by n bits on a two's complement signed binary number
has the effect of dividing it by 2n, but it always rounds down
(towards negative infinity). This is different from the way rounding
is usually done in signed integer division (which rounds towards 0).
This discrepancy has led to bugs in more than one compiler.
So what happens is, when shortened down to 8 bit, the following. In two's complement -5 would be
1111 1011
After the arithmetic right shift:
1111 1101
Now flip and add one to get the positive value for comparison:
0000 0011
Looks like a three to me.

Can't change -1 using right shift operattions

I can't seem to understand why does -1 isn't getting changed under bitwise shift.
why does -1>>1=-1?
A signed bit shift doesn't just shift the bits for negative numbers. The reason for this is you would get the wrong result. -1 in twos complement has all the bits set i.e. it's:
111111...1
If you were to just shift this you'd get:
011111....1
In two's complement this would be the representation of the largest positive number instead of anything that you might expect, it's the same for any negative number simply shifting would make the number positive. A simple way of implementing a right shift in twos complement is this:
rightShiftVal(int val) {
if (int < 0) {
int res = ~val; //not the value.
res = res >> 1; //do the right shift (the direction of the shift is correct).
res = ~res; //Back to twos complement.
return res;
}
return val >> 1;
}
If you put -1 into the above algorithm (i.e. 11111...111) when you not the value you get 0, when you shift the value you get 0, then when you not 0 you back to 11111....111, the representation of -1. For all other values the algorithm should work as expected.
Update
As suggested in one of the other answers you can also shift right and add the bit on at the far left i.e.
if (val < 0) {
unsigned uVal = val;
uVal = (uVal >> 1);
uVal = uVal | 0x80000000; //bitwise or with 1000...0
return uVal
}
Note that for this to work you have to put your int into an unsigned int so it doesn't do the signed bit shift. Again if you work through this with the value 11111...1 (the representation of -1) you are left with 11111....1, so there is no change.
Because >> operator is a signed right shift operator which fills in the bit by moving it by 1 with the sign bit in your case. See this for brief discussion.
The negative nos. are stored in the form of 2's complementin the memory.
So, if you have a no. -5 it will be stored as:
1111 1011
and 2's complement of -1 is: 1111 1111
So, when you right shift it you get 1111 1111 that is again -1.
Note:
1.While storing negative no. MSB is used as sign bit. 0 indicates positive no. and 1 indicates negative no.
2.When you right shift a positive no. a 0 is added to the left and for negative nos. 1 is added to keep the sign.