This question already has answers here:
What is “two's complement”?
(24 answers)
Closed 5 years ago.
Take a look at this compiler:
https://ideone.com/Y09Z0N
The code is very simple:
cout << ~5;
And this outputs -6
Now I'm no C++ guru, but somehow I remember that the ~ operator should flip a numbers bits, and since 5 is 101, I would expect to get 010, which is 2, or more precisely 5 is 0000......101 and I should get 1111...010 which should be a really big negative number and not 6 (110). The question is: am I wrong about the operator or am I missing something?
Negative integers are typically represented in two's complement.
This allows basic operations such as addition and subtraction to work with negative numbers in the exactly the same way as positive ones. In that form, negatives are represented as:
00000000 = 0
11111111 = -1
11111110 = -2
11111101 = -3
11111100 = -4
11111011 = -5
11111010 = -6
So indeed -6 = ~5
This is actually a subtle thing about two's complement.
I will write your numbers in base 16, at the size of the variable (I assume 32 bits, but you can alter the answer for other sizes).
5 is 0x00000005. ~5 is its negation, 0xFFFFFFFA. Add 5 to that, and you see ~5 + 5 is 0xFFFFFFFF. Add one more and you get 0x00000000, or 0, due to overflow.
Two's complement representation has made it so that incrementing past 0x7FFFFFFF (or 2147483647) is the actual overflow (and 0x80000000 is -2147483648), and simply the increment from -1 to 0 has been made not to cause an overflow.
You may read more about two's complement representation and also ask for more info from me if you wish.
Related
std::bit_width finds minimum bits required to represent an integral number x as 1+floor(log(x))
Why does std::bit_width return 0 for the value 0? Shouldn't it return 1, Since the number of bits required to represent 0 is 1?
Also, I think the 1 in the formula is an offset.
There is a strange bit of history to bit_width.
The function that would eventually become known as bit_width started life as log2, as part of a proposal adding integer power-of-two functions. log2 was specified to produce UB when passed 0.
Because that's how logarithms work.
But then, things changed. The function later became log2p1, and for reasons that are not specified was given a wider contract ("wide contract" in C++ parlance means that more stuff is considered valid input). Specifically, 0 is valid input, and yields the value of 0.
Which is not how logarithms work, but whatever.
As C++20 neared standardization, a name conflict was discovered (PDF). The name log2p1 happens to correspond to the name of an IEEE-754 algorithm, but it's a radically different one. Also, functions in other languages with similar inputs and results use a name like bit_length. So it was renamed to bit_width.
And since it's not pretending to do a logarithm anymore, the behavior at 0 can be whatever we want.
Indeed, the Python function int.bit_length has the exact same behavior. Leading zeros are not considered part of the bit length, and since a value of 0 contains all leading zeros...
Because mathematically it makes sense:
bit_width(x) = log2(round_up_to_nearest_integer_power_of_2(x + 1))
bit_width(0) = log2(round_up_to_nearest_integer_power_of_2(0 + 1))
= log2(1)
= 0
To elaborate what was said in the comments:
Assume "bit width" means "least number of bits required to store the (nonnegative integer) number". Intuitively we need at least log2(n) bits rounding up, so it is a formula close to ceil(log2(n)), so 255 would require ceil(log2(255)) = ceil(7.99..) = 8 bits, but this doesn't work for powers of 2, so we can add a fudge factor of 1 to n to get ceil(log2(n+1)). This happens to be mathematically equivalent to 1+floor(log2(n)) for positive n, but log2(0) is not defined or defined as something unuseful like negative infinitiy in the floor version.
If we use the ceiling formula for 0, we get the result. You can also see I didn't write out leading zeros, and as Nicol Bolas points out, 0 is all leading zeros.
n
bin(n)
bit_width(n)
8
1000
4
7
111
3
6
110
3
5
101
3
4
100
3
3
11
2
2
10
2
1
1
1
0
0
I wanted to test what happens when I write this code. I can not explain the following case:
Input: 5
Output: -6
#include <iostream>
int lastBit(int n){ return ~(n); }
int main() { std::cout << lastBit(5); }
Computers express negative numbers in quite a specific way. Values are always stored as series of bits and there is no way of introducing negative sign, so this has to be solved differently: one of bits plays role of a negative sign.
But this is not all - the system must be designed to handle maths properly (and ideally, the same way as for positive numbers).
So for instance 0 == 0b00000000. If you subtract 1 from 0, you get -1, but from the binary perspective, due to "binary underflow", 0b00000000 - 0b00000001 == 0b11111111, hence 0b11111111 == -1.
If you then subtract 1 from -1, you get 0b11111111 - 0b00000001 == 0b11111110 == -2. But 2 == 0b00000010, which shows, why -2 != ~2 (and the same rule applies to next values).
The very short, but maybe more intuitive answer might be: "-5 != ~5, because there is only one zero binarily (eg. 0 == -0), so there is always one more negative value than positive ones"
Not on all systems but on systems that use complement of two for signed values. By definition there, the binary representation of negative X = -n, where n is a positive integer, is ~n + 1, which allows signed and unsigned addition operations to be same.
Until C++20 result of ~(n) for signed negative n here would be undefined, because it depends on platform and compiler. In C++20 it's required to behave as if complement of two is used.
I found out the following
5 = 0101
Therefore, ~(5) = 1010
The 1 at the most significant bit denotes negativee (-)
010 = 6
Therefore, output is -6
Since this is a 2's complement machine
This question already has answers here:
bit-wise operation unary ~ (invert)
(5 answers)
Closed 7 years ago.
int x=10;
cout<<~x;
this code prints -11. if it was simple inversion then for 00001010 the bits should be 11110101, which on conversion to decimal is -117. I have tried searching but no luck pls tell what is happening here?
I am using mingw compiler, if its of any help.
That is working as expected. "11110101" is -11 in two's complement.
As a side note, "int" is either 16 or 32 bits, so you're actually talking about
"00000000 00001010" or "00000000 00000000 00000000 00001010" respectively.
~x is equal to −x − 1. Therefore, ~10 = -10 - 1 = -11.
Using 1-byte , 10 is represented as 0000 1010. Its bit-wise NOT is 1111 0101. Generally computer represents signed integers in 2's complement format. So, decimal equivalent of 1111 0101 is -11, How?
An N-bit number w represented in 2's complement as aN-1aN-2....a0 can be converted to decimal as
Therefore,
1111 01012 = -1*27 1*26 + 1*25 + 1*24 + 0*23 + 1*22 + 0*21 + 1*20 = -128 + 117 = -11
The ~ operator works as you think it does. It's just negative numbers don't work how you think they do. Negative numbers are encoded as a two's complement http://en.wikipedia.org/wiki/Two%27s_complement
Basically, the value of the highest bit is subtracted from the value of the lower bits.
This question already has answers here:
<< operator in C++?
(3 answers)
Closed 9 years ago.
I'm reading values from an accelerometer and saving them in a buffer called 'values'. Each accelerometer reading is 10 bits long, but the values are read in as bytes, so eah accelerometer reading is actually two bytes or two values in the 'values' buffer. This is sample code on how to combine those two bytes to get the one value:
x = ((int)values[1]<<8)|(int)values[0];
I get that I'm combining values[1] and values[2] and I'm pretty sure the (int) part is type casting those parts as integers (although I'm not sure why). The parts that have me really confused are <<8 and the vertical bar |. What are these two parts doing?
Thanks for any explanation and help you can give!
It's a bitmask.
You are left shifting (<<) the value in values[1] by 8 bit-positions. and then ORing (|) it to the value in values[0].
Please take some values and try to work through them. You will understand it better.
Here's a link for more reading and bit-manipulation examples.
This line of code combines two char into a int in a way that first char is moved 8 bits.
For example, value[0] = 5, value[1] = 1, then the read in value should be, 128 + 5 = 133. Because the high byte 1 means 128. Another way to look at it is:
x = ((int)values[1]<<8) + (int)values[0];
Replace or with +, it will be more readable. Hope this helps.
Take for example a 10-bit reading of 0101010111 in binary.
The lower 8 bits go to values[0] = 01010111 in binary (= 87 decimal).
The higher 2 bits go to values[1] = 01.
To recover the original 10-bit number from values:
(int)values[1] << 8 --> 01 << 8 --> 0100000000
values[1] is converted to a int (typically 32 bits) and then shifted left << 8 bits.
((int)values[1]<<8) | (int)values[0] --> 0100000000 | 01010111
or in vertical notation to express a bitwise-or:
0100000000
| 01010111
------------
0101010111
QED
The << operator shifts the bits in the second byte left by 8 bits so for example 0000000011111111 becomes 1111111100000000. The | is the binary "or" operator that combines the two bits in every position making it 1 if either bit or both bits are 1.
You have 2 bytes (1 byte = 8 bits) and you are trying to read in a 10 bit value, which is why you need 2 bytes instead of just using 1. When you are reading in the value you need to cast the 2 bytes to int so you can treat them like and integer value, but there is an issue, if value[1] is 3 (00000011) and the next byte value[0] is 227 (11100011) you can get a proper reading if you add them so you need to bit shift value[1] left by 8.
When you bit shift a unsigned char/char/byte by 8 you end up with 0, so you need to cast both value[1] and value[0] to an int so when you do the bit shift you end up with 768 (00000011 00000000) now you | that with value [0] and you end up with
(00000011 00000000 | 00000000 11100011) = (00000011 11100011) = 995
note I am only using 16bit ints so the example isn't full of a bunch of 0s.
If you have access to a programming calculator it can help you understand why you need to cast these byte values to ints, it can also just help you with casting in general. I would sugest playing around with the windows Calculator app for a bit if you have access to it. In order to get it into the programmer view go to view->programmer.
-5-8
Do we have to represent both integers in 2's complement form and then add?
Well, -5-8 is the same as -5 + -8, so if you were to take two's complement and add, you would get the answer (-13).
Another way to look at it, which is a little bit less work, is to see that -5 + -8 is -(5+8), so you could add 5+8 first, then take the two's complement.
You don't have to, but it's a correct solution, provided that the result will not overflow.
EDIT: By overflow I mean not fit in the representable range. For example in 4-bit arithmetic -8 is 1000, and -5 is 1011 (-8 + 3), so the result should be -13, but (1000 + 1011 = 10011), the leading 1 doesn't fit, and we get 3 istead of -13.