Go Down

Topic: Urgent - Split Long into 2 Int using BitShift (Read 6666 times) previous topic - next topic

robtillaart

#15
Jan 20, 2011, 06:17 pm Last Edit: Jan 20, 2011, 06:29 pm by robtillaart Reason: 1
with 32769 I read:

=> try 32769[glow]L[/glow]  (to be sure its a long)


Quote
With -1 as ValueLong I read on serial monitor:

L = 11111111111111111111111111111111
H = 11111111111111111111111111111111


because both L & H & ValueLong are signed, 1111...11 will read as -1 for all three of them. Bitwise it is a correct split.

Another way to split your long is to use an union, a less used construct in C++, A union has multiple var's mapped upon the same memory space:

Code: [Select]
union split_t
{
 int I[2];
 long ValueLong;
} X;

void setup()
{
 Serial.begin(115200);
}

void loop()
{
 X.ValueLong = -1;
 
 int H = X.I[0];
 int L = X.I[1];
 
 Serial.print(H, DEC);
 Serial.print(" = ");
 Serial.println(L,DEC);
 delay(500);
}


The union split_t could be extended with unsigned long or an array of four bytes. Although it seems that no math is involved the indexing of the array takes some cpu cycles ...
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

AWOL

#16
Jan 20, 2011, 06:38 pm Last Edit: Jan 20, 2011, 06:43 pm by AWOL Reason: 1
Pay more attention to your data types.
BTW, with 32 bit data types, a one-in-a-million chance means you have over 4000 chances to screw up!
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

jraskell

I'm not quite sure what your expectations are here.  The intermediate int decimal values will in no way correlate to the original long decimal value.  If they are only being used as a necessary step to transfer the entire data, then that doesn't matter.

What matters is that the bit representation is maintained.
Say you have a long value of (just for example) 1,582,081.
It's binary representation would be:
00000000 00011000 00100100 00000001

If you then assign that value to two ints with bitwise shifting, you would end up with
high int 00000000 00011000
low  int 00100100 00000001

If you then properly recompose that back into a new long, that new long will have the same decimal value as the previous one (assuming the binary representation of that decimal value is the same across any platform transitions).

You could use unsigned ints for your intermediate variables and it wouldn't make a difference.  You could even use 4 bytes or chars instead.

Quote

With -1 as ValueLong I read on serial monitor:

L = 11111111111111111111111111111111
H = 11111111111111111111111111111111


That looks completely correct.  Signed ints are stored in a twos complement format.  Google it for more info on how twos complement works, and why it's an ideal format to use for signed ints.

MatrixGTI

Quote
Pay more attention to your data types.
BTW, with 32 bit data types, a one-in-a-million chance means you have over 4000 chances to screw up!


Sorry but as I'm a noob in programming I have difficults to understand some things. Also english is not my language so...  ::)

Now I understand that variable are 32 bit long, this means that I can use Bitshift but in different way ?

Quote
because both L & H & ValueLong are signed, 1111...11 will read as -1 for all three of them. Bitwise it is a correct split.

Another way to split your long is to use an union, a less used construct in C++, A union has multiple var's mapped upon the same memory space:


I'll try with Union code, thanks for it, but I dont understand why bitshift did non work or I dont understand how to correctly read the variable sent

AWOL

How are you putting your two 16 bit value back together as a 32 bit value?
Not still multiplying by 32767 I hope.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

MatrixGTI

Quote
How are you putting your two 16 bit value back together as a 32 bit value?
Not still multiplying by 32767 I hope.


With my firt code (using /32767 etc ) I rebuild the Long with the reverse math method in VisualBasic

Long = ( H * 32767) + L

I know that this is not the right method, this is the reason why I ask to a forum users an alternative, but anyway it works.

If someone can write and example code using bitshift that works I'll study the background of the bit operation to understand it.

jraskell

The following should work to convert the two ints back into a long:

newlong = ((long)H << 16) | L;

But it will depend on the platform and programming environment you are working in to conver it back.  This assumes that H and L are two 16 bit variables, and that (long) is a 32 bit variable.  On most modern PCs and programming languages, ints are 32 bit variables and longs are 64 bit variables.  H and L may need to be declared as shorts and your 32 bit variable just declared as an int. (and the cast would be (int) instead of (long) as well)

AWOL

On a PC, both 'int's and 'long's are more likely to be 32 bits variables..
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

MatrixGTI

OK, I found a lot of examples for PC side , but at Arduino side ?

I can use >> 16 with or without mask if int variables are signed 32 bit ?

An example would be useful  ;)

Go Up