Confused with C++ "simple" calculation with sign & - c++

I am looking at a C++ source code where there is what looks to be a simply calculation. Yet with no knowledge in C++, I can't quite understand how it is really calculated (my goal being making the same calculation under Excel).
uint64_t fpo = (((ui>>32) << 24) | (ui & 0xffffff)) + 0x123e00;
PrintAndLog("ui result : %lld [0x%llX]", ui, ui);
In my case, ui is 0x0F007057B9
and the result is 0xF8295B9
If I take the windows Calculator, I do (in Hex mode)
(0x0F007057B9 AND 0xffffff) + 0x123e00
I am getting the same result (expect for the first 0xF)
I have read somewhere that AND returns 1 if both bits of same "weigh" are 1
So if I take ui AND 0xffffff converted to Binary :
0x0F007057B9 0000111100000000011100000101011110111001
0xffffff 111111111111111111111111
-------------------------------------------------------
0000111100000000011100000101011110111001
Which does make any change...
Am I completely going to wrong way?? Sorry for my poor english, I am from South Korea.
Thank you for helping me {^^;

For AND its
0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1
So if you AND a number with 0xffffff, you basicly just keep the numbers at those positions. You fill in the missing ones with 0.
In your case:
0x0F007057B9 0000111100000000011100000101011110111001
0xffffff 0000000000000000111111111111111111111111
-------------------------------------------------------
0000000000000000011100000101011110111001
Im not sure, if that was your question tho :)

Related

Why does this work for determining if a number is a power of 2?

int isPower2(int x) {
int neg_one = ~0;
return !(neg_one ^ (~x+1));
}
This code works, I have implemented it and it performs perfectly. However, I cannot wrap my head around why. When I do it by hand, it doesn't make any sense to me.
Say we are starting with a 4 bit number, 4:
0100
This is obviously a power of 2. When I follow the algorithm, though, ~x+1 =
1011 + 1 = 1100
XORing this with negative one (1111) gives 0011. !(0011) = 0. Where am I going wrong here? I know this has to be a flaw in the way I am doing this by hand.
To paraphrase Inigo Montoya, "I do not think this does what you think it does".
Let's break it down.
~x + 1
This flips the bits of 'x' and then adds one. This is the same as taking the 2's complement of 'x'. Or, to put it another way, this is the same as '-x'.
neg_one ^ (~x + 1)
Using what we noted in step 1, this simplifies to ...
neg_one ^ (-x)
or more simply ...
-1 ^ (-x)
But wait! XOR'ing something with -1 is the same as flipping the bits. That is ...
~(-x)
~(-x)
This can be simplified even more if we make use of the 2's complement.
~(-x) + 0
= ~(-x) + 1 - 1
= x - 1
If you are looking for an easy way to determine if a number is a power of 2, you can use the following instead for numbers greater than zero. It will return true if it is a power of two.
(x & (x - 1)) == 0

Reversed axis algorithm issue

I'm currently working on an electronic projet and there's a little problem with the joystick values. The values are "correct" but they looks weird.
A classical axis from a joystick usually work (for example left to right).
Totally left : -128
Center : 0
Totally left : +128
But here's what I read from this one :
Totally left : -0
Slightly on the left : - 128
Center : "Random" (never totally zeroed, float between -125 and +125)
Slightly on the right : + 128
Totally right : +0
For the moment I'm using the following workaround to get a linear progression from -128 to +128 :
if (value > 0)
value = -(128 - value);
else
test = 128 + value;
The problem is I have to do that on several inputs, 2 axis per joyrstick, 3 joystick per device, 4 total devices so 24 times and I need to need keep a response time under 20ms for the entire operation. And that's freaking cycle consuming !
I can binary manipulate the value.
Here's how I actually center it. Raw dump contains array of 0 and 1 read from the controller I/O
for (i = 0; i<8; i++) {
value |= raw_dump[pos + i] ? (0x80 >> i):0 ;
}
Do you have any ideas or good algorithm ? I'm starting to be desesperate and I totally suck on binary manipulation... :'(
It looks like whatever mechanism is sampling the joystick actually returns an unsigned byte in the range of 0 .. 255, with 0 at the far left and 255 at the far right.
You can convert that value to the range -128 to 127 with one statement:
value = (value & 0xFF) - 128;
If value is a byte variable, you can shorten that to:
value ^= 0x80;
That conversion should be very quick on any processor, even a 1MHz 6502.
I'm not sure what your second bit of code is about. If you could describe what you're trying to accomplish there, I can offer further insight.

Operations on bits, getting the bigger value

I'm not familiar with bitwise operations. I have this sequence:
1 0 0 0 0 : 16
---------------
0 1 1 1 1 : 15
---------------
0 1 1 1 0 : 14
---------------
.
.
.
---------------
0 0 0 1 1 : 3
---------------
0 0 0 1 0 : 2
---------------
0 0 0 0 1 : 1
---------------
I want to check first if there is more than one "1". If that's the case, I want to remove the one that has the bigger decimal value, and to finish, getting the bigger remaining. For example 15, there is four "1", I remove the bigger one, the "1" at "8", I got "0 0 1 1 1 : 7", where the bigger "1" is at "4". How can I do this?
Here's the code that does what you want:
unsigned chk_bits(unsigned int x) {
unsigned i;
if (x != 0 && (x & (x-1)) != 0) {
/* More than one '1' bit */
for (i = ~(~0U >> 1); (x & i) == 0; i >>= 1)
; /* Intentionally left blank */
return x & ~i;
}
return x;
}
Note that I assume you're dealing with unsigned numbers. This is usually safer, because right shifting is implementation defined on signed integers, because of sign extension.
The if statement checks if there's more than one bit set in x. x & (x-1) is a known way to get a number that is the same as x with the first '1' least significant bit turned off (for example, if x is 101100100, then x & (x-1) is 101100000. Thus, the if says:
If x is not zero, and if turning off the first bit set to 1 (from LSB to MSB) results in something that is not 0,
then...
Which is equivalent to saying that there's m ore than 1 bit set in x.
Then, we loop through every bit in x, stopping in the first most significant bit that is set. i is initialized to 1000000000000000000000000000, and the loop keeps right shifting it until x & i evaluates to something that is not zero, at which point we found the first most significant bit that is 1. At that point, taking i's complement will yield the mask to turn off this bit in x, since ~i is a number with every bit set to 1 except the only bit that was a 1 (which corresponds to the highest order bit in x). Thus, ANDing this with x gives you what you want.
The code is portable: it does not assume any particular representation, nor does it rely on the fact that unsigned is 32 or 64 bits.
UPDATE: I'm adding a more detailed explanation after reading your comment.
1st step - understanding what x & (x-1) does:
We have to consider two possibilities here:
x ends with a 1 (.......0011001)
x ends with a 0 (.......0011000)
In the first case, it is easy to see that x-1 is just x with the rightmost bit set to 0. For example, 0011001 - 1 = 0011000, so, effectively, x & (x-1) will just be x-1.
In the second case, it might be slightly harder to understand, but if the rightmost bit of x is a 0, then x-1 will be x with every 0 bit switched to a 1 bit, starting on the least significant bits, until a 1 is found, which is turned into a 0.
Let me give you an example, because this can be tricky for someone new to this:
1101011000 - 1 = 11101010111
Why is that? Because the previous number of a binary number ending with a 0 is a binary number filled with one or more 1 bits in the rightmost positions. When we increment it, like 10101111101111 + 1, we have to increment the next "free" position, i.e., the next 0 position, to turn it into a 1, and then all of the 1-bits to the right of that position are turned into 0. This is the way ANY base-n counting works, the only difference is that for base-2 you only have 0's and 1's.
Think about how base-10 counting works. When we run out of digits, the value wraps around and we add a new digit on the left side. What comes after 999? Well, the counting resets again, with a new digit on the left, and the 9's wrap around to 0, and the result is 1000. The same thing happens with binary arithmetic.
Think about the process of counting in binary; we just have 2 bits, 0 and 1:
0 (decimal 0)
1 (decimal 1 - now, we ran out of bits. For the next number, this 1 will be turned into a 0, and we need to add a new bit to the left)
10 (decimal 2)
11 (decimal 3 - the process is going to repeat again - we ran out of bits, so now those 2 bits will be turned into 0 and a new bit to the left must be added)
100 (decimal 4)
101 (decimal 5)
110 (the same process repeats again)
111
...
See how the pattern is exactly as I described?
Remember we are considering the 2nd case, where x ends with a 0. While comparing x-1 with x, rightmost 0's on x are now 1's in x-1, and the rightmost 1 in x is now 0 in x-1. Thus, the only part of x that remains the same is that on the left of the 1 that was turned into a 0.
So, x & (x-1) will be the same as x until the position where the first rightmost 1 bit was. So now we can see that in both cases, x & (x-1) will in fact delete the rightmost 1 bit of x.
2nd step: What exactly is ~0U >> 1?
The letter U stands for unsigned. In C, integer constants are of type int unless you specify it. Appending a U to an integer constant makes it unsigned. I used this because, as I mentioned earlier, it is implementation defined whether right shifting makes sign extension. The unary operator ~ is the complement operator, it grabs a number, and takes its complement: every 0 bit is turned into 1 and every 1 bit is turned into 0. So, ~0 is a number filled with 1's: 11111111111.... Then I shift it right one position, so now we have: 01111111...., and the expression for this is ~0U >> 1. Finally, I take the complement of that, to get 100000...., which in code is ~(~0U >> 1). This is just a portable way to get a number with the leftmost bit set to 1 and every other set to 0.
You can give a look at K&R chapter 2, more specifically, section 2.9. Starting on page 48, bitwise operators are presented. Exercise 2-9 challenges the reader to explain why x & (x-1) works. In case you don't know, K&R is a book describing the C programming language written by Kernighan and Ritchie, the creators of C. The book title is "The C Programming Language", I recommend you to get a copy of the second edition. Every good C programmer learned C from this book.
I want to check first if there is more than one "1".
If a number has a single 1 in its binary representation then it is a number that can be represented in the form 2x. For example,
4 00000100 2^2
32 00010000 2^5
So to check for single one, you can just check for this property.
If log2 (x) is a whole number then it has single 1 in it's binary representation.
You can calculate log2 (x)
log2 (x) = logy (x) / logy (2)
where y can be anything, which for standard log functions is either 10 or e.
Here is a solution
double logBase2 = log(num)/log(2);
if (logBase2 != (int)logBase2) {
int i = 7;
for (;i >0 ; i--) {
if (num & (1 << i)) {
num &= ~(1 << i);
break;
}
}
}

1+2+4 in Binary bits

I have an email from a developer in which he says:
As you may know 1110000000000000 means 1+2+4
I won't be able to contact him for a few days. Can anyone else explain how that is possible?
Numbers appear to be turned into binary using the following function:
function toBinaryString(bitmask)
tvar2 = 0
tvar3 = 1
tvar1 = ""
do while tvar2 < 16
if (bitmask and tvar3) > 0 then
tvar1 = tvar1 & "1"
else
tvar1 = tvar1 & "0"
end if
tvar3 = tvar3 * 2
tvar2 = tvar2 + 1
loop
toBinaryString = tvar1
end function
It's little endian notation (Wiki). Basicaly the least significant bits appear on the left, unlike big endian notation (which is what most people think of when talking about binary).
As such the first bit represents 0^2, then 1^2, 2^2 etc. (so 1 + 2 + 4).
Prepare for some interesting reading material: How bytes work
Actually your developer is not correct, 1110000000000000 in binary notation is 57344 in decimal notation.

is VAR |= 1 << 2; reverisble?

First I am not sure what is going on in this bitwise operation.
I get code written and supply to other parties as code snippets.
Now if VAR is unsigned 8bit integer (unsigned char) and r is either 0 or 1 or 2 or 4.
Can following be reversed if the value of r is known and resulting value is there.
VAR |= 1 << r; //that is 200 where VAR was 192 and r was 3
For example initial value of VAR is 192 and value of r is 3 *result is 200*.
Now if I have this 200, and I know the value of r that was 3, can I reverse it back to 192 ?
I hope it is most easy one, but I don't know these bitwise operations, so forgive me.
Thanks
The answer is no. This is because the | (OR) operator is not a one-to-one function.
In other words, there are multiple values of VAR that can produce the same result.
For example:
r = 3;
var0 = 8;
var1 = 0;
var0 |= 1 << r; // produces 8
var1 |= 1 << r; // produces 8
If you tried to invert it, you wouldn't be able to tell whether the original value is 0 or 8.
A similar situation applies to the & AND operator.
From an information-theory perspective:
The operators | and & incur a loss of information and do not preserve the entropy of the data.
On the other hand, operators such as ^ (XOR), +, and - are one-to-one and thus preserve entropy and are invertible.
No, OR is not reversable. I believe only XOR is.
For example, if variable a contains 1001 1100 or 1001 1000, and you set the third bit (from the right) to 1 regardless of what the initial value is, then both 1001 1100 and 1001 1000 as source operands would result in the same value (1001 1100).
Firstly, 1<<2 is just another way of writing "4" or 100 in binary.
The |= operator is another way of writing x = x | y;
The end result is setting bit 2 in x. If bit 2 in x was zero then reversing it would be to clear bit 2. If bit 2 was 1, then it's a no-op.
The problem with your question is that you don't know ahead of time what the initial state of bit 2 was.
If your goal was to clear bit 2 you can do this:
x &= ~(1<<2);
Given an expression result |= 1 << shiftAmount, corresponding to VAR and r in your original example, you can use the following to do the exact opposite:
result &= ~(1 << shiftAmount)
Note that this is not a pure inverse, because bitwise-or is not a one-to-one function. Bitwise-or sets one or more bits to 1, whether or not they were already 0 or 1. The expression I have shown above will always set the associated bits to 0, so if the bit was 1 originally it will not go back to its original state.
No, you can't reverse an OR operation.
In your example, with r=3, both the starting values VAR=192 and VAR=200 will result in 200.
Since there are two input values that will give the same result, you won't know which one to go back to.