# bitmath confusion

Hi
I’m trying to develop my Arduino programming chops, by exploring lower-level coding - not for any specific project or reason, other than to develop new skills.

I’ve begun with simple bitmath operations, and it all seems very clear so far except for one thing. If I do this:

``````//visualise the bit operation
//caused by NOT:

void setup() {
Serial.begin(19200);
int x = 350;
int y = ~x;//invert each bit
Serial.println(x, BIN);
Serial.println(y, BIN);
}

void loop() {
}
``````

I’ll get the expected binary equivalent of 350 (or any other positive integer <32767) , but the y (~= x) value is output as two 16-bit integers, the first of which is a stream of 1’s. I realise this is a n00bish question, but why does the ‘inverse’ of a positive integer require two 16-bit ints.

I had a look at the wikipedia entry for 2’s complement, but I’m afraid my maths is very weak.

I’ll probably never have an explicit practical need for using negative integers (at the moment) - I just don’t like having a gap in my knowledge, cos everything else so far is clear.

I realise this is a n00bish question, but why does the 'inverse' of a positive integer require two 16-bit ints.

What happens when you invert the sign bit (which you are doing)?

Bit math should generally ONLY be done on unsigned variables.

First of all, two 16 bit ints would have 32 digits. So count your digits again, you will find 16.

Both positive and negative int types in C use 16 bits. It's just that println() doesn't print leading zeros. But a negative two's complement number has a leading one- the sign bit.

I don't know if ~x will invert each bit of an int.

But if it does, that's not how you calculate the two's complement of the original number, anyway.

350 == 0000 0001 0101 1110 in 16 bit binary

-350 == 1111 1110 1010 0010

which, you will notice, is not the same as inverting each bit

That is exactly what tilde does Tilde

Bit by bit is directly inverted, which gives surprising results on integers. Because it is intended to work on bits only, not integers. Exactly as stated in the reference.

Thats why you run into the sign bit problem, and the two's complement not done, when you try apply the method to integers.

Anders53:
That is exactly what tilde does Tilde

Bit by bit is directly inverted, which gives surprising results on signed integers.
Because it is intended to work on bits unsigned types only, not signed integers.
Exactly as stated in the reference.

Thats why you run into the sign bit problem, and the two’s complement not done, when you try apply the method to signed integers.

However, the original poster's code produces the same output regardless of whether the int variables x and y are signed or unsigned. So the confusion is not based on that fact. Perhaps adding the additional line:

``````  Serial.println(-x, BIN);
``````

and observing the output, would help to expand the understanding.

Hi many thanks for the rapid responses. I think I should illucidate my original confusion: if I do this:

``````void setup()(
Serial.begin(19200);
int x = 32737;
int y = ~x;
Serial.println(x, BIN);
Serial.println(y, BIN);
}
``````

I know what decimal values to expect. My 'C-primer' tells me that doing NOTx is the same as -x-1, so in decimal x = 32737 and y = -32738. This much is clear. But when I look in my serial monitor window this is what is see:

111111111100001 1111111111111111000000000011110

I don't see where the 'extra' 16 ones come from; is this to make it fold over into the negative domain?

Thanks again

Look at the source code in the Print.cpp file: the argument is cast to a 32 bit long value before it is printed; a negative int will be a long with the upper 16 bits set to 1.

kind regards,

Jos

Ok, thanks.

I tried to print a simple negative number, and it also is 32-bits long, as you describe.

Could you provide a clue to the location of the Print.cpp file; just out of interest.

Thanks

Solved:

I just used unsigned int, and the serial monitor gives me what I expect.

Thanks everyone

It’s in your IDE directory in: hardware/ardiuno/avr/cores/aruino.

kind regards,

Jos