How is a max signed byte -1? [duplicate] - bit-manipulation

This question already has answers here:
What is “two's complement”?
(24 answers)
Closed 1 year ago.
I am really curious and confused:
how is 0xFFFF (0b11111111111111) or 0xFF (0b11111111) -1?
if 0b01111111 is 127 and the first bit indicates that it is a positive number then shouldn't 0b11111111 be -127?
Am I missing something???

Two's complement form is commonly used to represent signed integers. To swap the sign of a number this way, invert all the bits and add 1. It has the advantage that there is only one representation of zero.
01111111 = 127
To get -127 flip the bits:
10000000
And add 1:
10000001
To negate 1:
00000001
11111110 // flip
11111111 // + 1
With 0:
00000000
11111111 // flip
00000000 // + 1 (the carry bit is discarded and it's still 0)
And just to show it works going the other way:
With -127:
10000001
01111110 // flip
01111111 // + 1 and you are back to +127.

Related

How come 129, which is 8-bit number, is stored as -127 in signed char in c++

I declared signed char and stored 129, an 8-bit number, in it. when typecasted it into integer and printed the result, its -127. I understand that it is overflow, but the confusion occurs when you look at the binary of 129 which is 10000001. In signed char, most significant bit is reserved as a sign bit and rest of the 7 bits are used to store the number's binary. According to this concept, 129 should be stored as -1. MSG representing negative sign and rest of the 7-bits are 0000001 which makes 1.
How come 129 becomes -127 when the binary of 129 makes -1.
#include <iostream>
using namespace std;
int main() {
char a=129;
cout<<(int) a; // OUTPUT IS -127
return 0;
}
Your current idea of negative numbers is like this:
00000001 == 1
10000001 == -1
01111111 == 127
11111111 == -127
This means that you have only available range of integers -127...127 and
also you have two zeros. (00000000 == 0 and 10000000 == -0)
Best method is so called two's complement. For any number x, you negate binary representation and add 1 to get -x.
It means:
00000001 == 1
11111111 == -1
01111111 == 127
10000001 == -127
10000000 == -128
In this way only 00000000 is zero and you have the widest range -128...127.
Also CPU don't need additional instructions for adding signed numbers because it's identical to unsigned number addition and subtraction.
You may wonder, why to add 1. Without it, it's called one's complement.
https://en.wikipedia.org/wiki/Ones%27_complement
Every current computer stores low level signed integers in a format known as two's complement.
In two's complement, MAX_POSITIVE+1 is MIN_NEGATIVE.
0x00000000 is 0.
0x00....0V is V.
0x01....11 is MAX_POSITIVE
0x10....00 is MIN_NEGATIVE
0x11....11 is -1.
This looks weird at first glance.
But, it means that the logic of addition for positive and negative numbers is the same. In fact, signed and unsigned math works out to be the same, except on overflow a positive signed number becomes a negative number, while the overflow of a positive unsigned number wraps around to 0.
Note that in C++, overflowing a signed number is undefined behavior, not because the hardware traps it, but because by making it UB the compiler is free to assume "adding positive numbers together is positive". But at the machine code level, the implementation is 2s complement, and C++ has defined converting from signed to unsigned as following the 2s complement assumption.

Seven bit and two compliment

If we use seven-bit two's complement binary representation for integers, what is
The number of integers (things) that can be represented in this way?
The smallest (most) negative integer that can be represented in this way?
The largest positive integer that can be represented in this way?
This is a CS homework question that I am having trouble answering and explaining. Any help would be appreciated.
So its really easy
Counting in binary usually goes like
>00000000 (8) = 0
>00000001 (8) = 1
>00000010 (8) = 2
>00000011 (8) = 3
>etc...etc.
In 7 bit the last bit is what decides if its a negative or positive
1 being negative and 0 being positive
> 10000000 = -128
> 10000001 = -127
> 10000010 = -126
> On...and on...
> 11111111 = -1
> 00000000 = 0
> 00000001 = 1
> 01111111 = 127
So lowest you can go is -128
Highest you can go is 127
Approved answer is not correct.
With 7-bits of 2's complement, it could range from -64 to 63. (traditionally, 7 bits can only go up to 2^n-1 which is 128 but MSB is reserved for sign, so we could have 6 bits to represent the data.
We will be getting 64 positive and 63 negative values and answer should be -64, 63.)
No, because in two's complement, the most significant bit is the sign bit. 0000001 is +1, a positive number.
That is why the range of two's complement 7-bit numbers is -64 to 63, because 64 is not representable (it would be negative number otherwise).
The most negative number is 1000000. The leading 1 tells you it's negative, and to get the magnitude of the number, you flip all the bits (0111111), then add one (1000000 = 64). So the resulting number is -64 thru 63.
For largest positive integer in 2's complement use the formula
(2^(n-1)-1)
That is (2^(7-1)-1)=63
For the smallest use
-2^n-1
That is -2^7-1=-64

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

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.

How does C++ do bitwise "or" operations on negative numbers?

When I give to a variable such value: e = 17|-15; , I get -15 as an answer after compiling.I can't understand what arithmetic c++ uses. How does it perform a bit-wise OR operation on negative decimals?
It's just doing the operation on the binary representations of your numbers. In your case, that appears to be two's complement.
17 -> 00010001
-15 -> 11110001
As you can see, the bitwise OR of those two numbers is still -15.
In your comments above, you indicated that you tried this with the two's complement representations, but you must have done something wrong. Here's the step by step:
15 -> 00001111 // 15 decimal is 00001111 binary
-15 -> ~00001111 + 1 // negation in two's complement is equvalent to ~x + 1
-15 -> 11110000 + 1 // do the complement
-15 -> 11110001 // add the 1
It does OR operations on negative numbers the same way it does so on positive numbers. The numbers are almost certainly represented in two's-complement form, which gives you these values:
17 = 0000000000010001
-15 = 1111111111110001
As you can see, all the bits of 17 are already set in −15, so the result of combining them is again −15.
A bitwise or with a negative number works JUST like a bitwise or with a positive number. The bits in one number are ored with the bits in the other number. How your processor represents negative numbers is a different matter. Most use something called "two's complement", which is essentially "invert the number and add 1".
So, if we have, for simplicity, 8 bit numbers:
15 is 00001111
Inverted we get 11110000
Add one 11110001
17 is 00010001
Ored together 11110001
17 = b00010001
-15 = b11110001 <--- 2s complement
| -15 = b11110001
The operator | is a "bitwise OR" operator, meaning that every bit in the target is computed as the OR-combination of the corresponding bits in the two operands. This means, that a bit in the result is 1 if any of the two bits in the numbers at the same positions are 1, otherwise 0.
Clearly, the result depends on the binary representation of the numbers which again depends on the platform.
Almost all platforms use the Two's complement, which can be thought as a circle of unsigned numbers, in which negative numbers are just in the opposite direction than positive numbers and "wrap around" the circle.
Unsigned integers:
Signed integers:
The calculation of your example is as follows.
17: 00000000 00000000 00000000 00010001
-15: 11111111 11111111 11111111 11110001
------------------------------------------
-15: 11111111 11111111 11111111 11110001
you have to looks at how the bits work
Basically, if either number has a 1 in a particular spot, than the result will also have a 1
-15 : 11110001 (two's complement)
17 : 00010001
-15 | 17 : 11110001
as you can see, the result is the same as -15

Weird output for bitwise NOT

I am trying to take one's complement of 0 to get 1 but I get 4294967295. Here is what I have done:
unsigned int x = 0;
unsigned int y= ~x;
cout << y;
My output is 4294967295 but I expect 1, why is this so? By the way, I am doing this in C++.
Why do you expect 1? Bit-wise complement flips all the bits.
00000000000000000000000000000000 = 0
|
bitwise NOT
|
v
11111111111111111111111111111111 = 4294967295
Perhaps you are thinking of a logical NOT. In C++ this is written as !x.
You have to look at this in binary to understand exactly what is happening.
unsigned int x = 0, is 00000000 00000000 00000000 00000000 in memory.
The ~x statement flips all bits, meaning the above turns into:
11111111 11111111 11111111 11111111
which converts to 4294967295 in decimal form.
XOR will allow you flip only certain bits. If you only want to flip the least significant bit, use x ^ 1 instead.
Where did you get the expectation of 1 from?
Your understanding of bitwise operations clearly shows is lacking, it would be prudent to work through them first before posting in here...
you're not confusing with a ! which is a logical NOT, are you?
a ~ bitwise complement or a bitwise NOT operation flips all the bits from 1 to 0 and vice versa depending on where in the bitmask is set, so for example, a 1 is
00000000 00000000 00000000 00000001
doing a ~ bitwise NOT on that flips it to
11111111 11111111 11111111 11111110
which gives you the maximum value less 1 of the integer datatype on a 32bit system.
Here is a worthy linky to this which shows you how to do bit-twiddling here.
An integer is more than just 1 bit (it's 4 bytes, or 32 bits). By notting it, you'r flipping everything, so in this case 00000... becomes 11111...
~ flips all of the bits in the input. Your input is an unsigned int, which has 32 bits, all of which are 0. Flipping each of those 0-bits gives you 32 1-bits instead, which is binary for that large number.
If you only want to flip the least significant bit, you can use y = x ^ 1 - that is, use XOR instead.
You can use
unsigned int y= !x;
to get y = 1;