Pages: 1 [2]   Go Down
Author Topic: Urgent - Split Long into 2 Int using BitShift  (Read 4432 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12465
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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 ...
« Last Edit: January 20, 2011, 12:29:18 pm by robtillaart » Logged

Rob Tillaart

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

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 239
Posts: 24371
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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!
« Last Edit: January 20, 2011, 12:43:20 pm by AWOL » Logged

"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.

New Hampshire
Offline Offline
God Member
*****
Karma: 13
Posts: 779
There are 10 kinds of people, those who know binary, and those who don't.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged


0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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...  :smiley

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
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 239
Posts: 24371
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

"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.

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

New Hampshire
Offline Offline
God Member
*****
Karma: 13
Posts: 779
There are 10 kinds of people, those who know binary, and those who don't.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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)
Logged


Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 239
Posts: 24371
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

On a PC, both 'int's and 'long's are more likely to be 32 bits variables..
Logged

"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.

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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  smiley-wink
Logged

Pages: 1 [2]   Go Up
Jump to: