Sign in to follow this  

Serialize - data packing

This topic is 4275 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I understood the concept, and after a quick pull, I double checked my mental code.

Link.

Fundamentals, bits are what makes a byte. The higher the bit in the sequence, the greater the number it represents. Each bit represents a 2^x number. Normally, we would copy byte for byte, using the & (bit-wise AND) with 255 to determine which bits we want. However, we're doing 4 bytes at a time, so we will have to use the number 4294967295. This sets 32 bits to '1's.

So, follow the code carfully:


double PackFloats(float f1, float f2)
{
return ((double)f1 << 32) + ((double)f2);
}



EDIT: Hit the button too soon. The << is an operator that "shifts" bits. Basically, you're telling the computer that you want to fill in 4 bytes of the double with f1, starting at bit 32, and ends up at bit 63, the last bit (remember, we have bit 0 that makes it a total of 64 bits).

Share this post


Link to post
Share on other sites
Um, packing two small units into a meaningful larger unit only works with unsigned integers. The last bit of code gives you a structure of either two floats or a double.

u.f1 = your_float1;
u.f2 = your_float2;
your_double = u.d;

Is basically filling your_double with meaningless bits.

The
struct float2{
float f1,f2;
}
is most likely what the OP is looking for.

Share this post


Link to post
Share on other sites
Quote:
Original post by Cocalus
Um, packing two small units into a meaningful larger unit only works with unsigned integers. The last bit of code gives you a structure of either two floats or a double.

u.f1 = your_float1;
u.f2 = your_float2;
your_double = u.d;

Is basically filling your_double with meaningless bits.

The
struct float2{
float f1,f2;
}
is most likely what the OP is looking for.


He has a good point, as floating point precision would get messed up...

But he's just trying to back it up so he could extract it later, would that affect it?

Share this post


Link to post
Share on other sites
Let me add to my previous post here.

How would you de-searilize it?

With a function like the one before, except those numbers that I showed you would actually come into play. Observe:


struct MyStruct
{
float f1;
float f2;
}

MyStruct ExtractDouble(double tempD)
{
MyStruct returnS;
returnS.f2 = tempD & 4294967295;
returnS.f1 = (tempD >> 32) & 4294967295;

return returnS;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by dbzprogrammer
double PackFloats(float f1, float f2)
{
return ((double)f1 << 32) + ((double)f2);
}

This works with interegs but not with doubles:
error C2296: '<<' : illegal, left operand has type 'double'

Share this post


Link to post
Share on other sites
If he's just packing it to extract it latter then the 2 float structure is what he wants. Using a double is just confusing

This has nothing to do with precision the data structure of a float. They just don't pack like that (the double is as usefull as a random bunch of bits).

A float is
1 sign bit 8 Exponent bits 23 Precision Bits
A double is
1 sign bit 11 Exponent bits 53 Precision Bits

So 2 floats packed into a double like that is
1 sign 8 exponent 23 Precision 1 sign 8 exponent 23 Precision
Where only the first one sign bit lines up with the double.

You can pull the floats back out. But why use a double at all when the structure works just as well and is descriptive of what you're doing.

(Note I'm assuming the compiler packs structures on 4 byte alignments)

Share this post


Link to post
Share on other sites
Quote:
Original post by Cocalus
Is basically filling your_double with meaningless bits.

But it works...

#include <iostream>
using namespace std;
union U
{
struct {
float f1,f2;
};
double d;
};
int main()
{
//Serialize
U u;
u.f1 = 2.8;
u.f2 = 3.1;
double d = u.d;
//Deerialize
U u2;
u2.d = d;
float f1 = u2.f1;
float f2 = u2.f2;
cout << f1 << endl << f2 << endl;
}
/*
Output:
2.8
3.1
*/






OK...
I would use just a struct as I said in my first post.
Or the std::pair class.

Share this post


Link to post
Share on other sites
My point is that involving the double is unneeded and confusing.

U u;
u.f1 = 2.8;
u.f2 = 3.1;

float f1 = u.f1;
float f2 = u.f2;

works just as well and is easier to understand.

Share this post


Link to post
Share on other sites
It is confusing and is it not needed he can use unsigned __int64 too(better than the double)... but he asked how to do it and I just answered.

Share this post


Link to post
Share on other sites
If you want to serialize it to something like a vector<char> buffer, you could write a bunch of serialization/unserialization functions:

(alternatively, and probably more cleanly, you could make these Get/Put functions member functions of some class, and manage the vector or some other buffer behind closed doors.)


void PutFloat( std::vector<char>& vec, float data )
{
vec.insert( vec.end(), reinterpret_cast<char const*>( &data ), reinterpret_cast<char const*>( &data + 1 ) );
}

float GetFloat( std::vector<char> const& vec, std::size_t index )
{
if( index < index + sizeof(float) && index + sizeof(float) <= vec.size() )
{
float val = *reinterpret_cast<float const*>( &vec[index] );
return val;
}

//access would overflow vector boundaries - throw something?
return 0.0f;
}





[Edited by - RDragon1 on April 1, 2006 4:40:10 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Kambiz
It is confusing and is it not needed he can use unsigned __int64 too(better than the double)... but he asked how to do it and I just answered.


I was just trying to get across that there are very few good reasons for ever doing it like that.

Share this post


Link to post
Share on other sites
Quote:

Original post by Eitsch
...not an array or vector...


Quote:

Original post by RDragon1
If you want to serialize it to something like a vector<char> buffer,...

Share this post


Link to post
Share on other sites
Quote:
Original post by Kambiz
Quote: Original post by Eitsch
...not an array or vector...

Quote: Original post by RDragon1
If you want to serialize it to something like a vector<char> buffer,...


Oops, good call. I saw someone mentioning network serialization, so I threw that up...

That just raises the question - why not a vector?

Share this post


Link to post
Share on other sites
Quote:
Original post by RDragon1
That just raises the question - why not a vector?


Unrelated to your question, but also a valid one: Why not endianness?

OP, you might want to check the enginuity articles for some developed ideas on serialization that might inspire you.

Share this post


Link to post
Share on other sites
Why not a vector?
That is a good question... I know another one : why do you want to serialize just 2 floats??
...and another one : Why do you need serialization?

Share this post


Link to post
Share on other sites
Quote:
Original post by owl
Quote:
Original post by RDragon1
That just raises the question - why not a vector?


Unrelated to your question, but also a valid one: Why not endianness?

OP, you might want to check the enginuity articles for some developed ideas on serialization that might inspire you.


*nod*

For endianness, I would pick the dominant platform (the one used the most, if there is one), and pack things in using the native endianness. That gives you the most efficient and clean code where you care about it most. Then, on the non-dominant supported platform, have the packing/unpacking convert to/from the dominant endianness.

Share this post


Link to post
Share on other sites
i need it to send a big structure over network (i am using simple sockets). the big structure has many dynamic stuff and pointers so i wanted to put it into one big "buffer" (a buffer where i don't loose precision if i have floats). RDragon1s code looks good. thanks.

Share this post


Link to post
Share on other sites

This topic is 4275 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this