Hell ho !
I want to be able to send some double values over a network, but as I want to do it the right way I am in search of some converting function.
Have you ever hear about something as ntohd, htond functions ?
No such function. Doubles are stored in IEEE-754 format on Intel, the same may be true for Macs. This being the case, you can simply transfer them as data.
As discussed before, it can often be more efficient to send numbers as text. It can even be more accurate if the numbers are rational e.g. 0.1
Not that the gained accuracy means anything, since you'll just convert it to base 2 when you receive it.
extern int StringToNumber(string MyString) { istringstream converter(MyString); int result; converter >> result; return result; } extern string NumberToString(int Number) { ostringstream converter; converter << Number; return converter.str(); }
Great, and it has nothing to do with doubles
Just use that templated one posted a while back.
It's true, but at least you can be sure the other side can convert it to its own format, using strtod() and sprintf()
Thanks to All, thanks to piccolo too ( even if you were not seeing what the question was ).
CGamesPlay: I was thinking so but waiting for someone to confirm.
Matt Smith: I got big and tons of values. Using sprintf trick is too much cost.
What I got tested: same byte order in all Intel/Amd. seem reversed for Sun/Aix.
A good job has been made there
I am waiting for BAF and his link !
I want to give cookies !
Quick !
You could also use Allegro fixed point datatype. It should have guaranteed percision on all platforms. Only problem is limited range and percsision.
Basically all machines use IEEE-754 floating point format. However, the endianess of this value is like any other issue. What I did for my network library GNE is to say that all values will be sent little-endian (I chose this because I expect virtually all peers to be little-endian). For floating point I said that I will send in little-endian IEEE-754 single or double precision. Well, Intel and Sun and PPC machines all use IEEE-754, so what the plan is just to say machines that don't support IEEE-754 are just simply "not supported" by any current port of GNE, and if I really need to do it, it isn't too onerous to actually parse a IEEE-754 number by breaking it into its components then using portable C to "convert" it to a float/double. But since I can't find a computer you actually need to do this for nor expect any target user of my library to have one, I never wrote the code.
So, in other words, do whatever you want as long as you precisely define it and give yourself a way out. If that's true, then if the unexpected happens, you can actually perform the work.
I don't recall what thread it was in, but it was something like (untested code I just wrote):
template<typename t> t ReadNum(std::string src) { t ret; std::stringstream s(src); s >> ret; return ret; } template<typename t> std::string WriteNum(t src) { std::stringstream ret; s << src; return s.str(); }
You would do something like:
string myString = WriteNum(myFloat); // then: float myFloat = ReadNum<float>(myString);
Again, untested, but probably works.
What gillius said. Something like:
That requires that ints be 32 bit types. There's no pretty (by pretty I mean, without ifdefs) way to do the same for doubles, because doubles are 64 bit and there's no standard endianness conversion function for 64 bit values.
I do not like the use of text for this purpose. The advantages are that it is a variable length format that the standard library already supports. The disadvantages are that it has a space efficiency < 50% and its decimal nature makes it use more cycles than is needed for something as simple as encoding a floating point value.
If you were going to use text-based packets anyway though, why make your packets be stringstreams instead of using ReadNum/WriteNum wrappers?
edit:added missing paren
untested, but probably works.
Heres a more optimized version:
template<typename t> t ReadNum(std::string src) { t ret; std::istringstream s(src); s >> ret; return ret; } template<typename t> std::string WriteNum(t src) { std::ostringstream ret; s << src; return s.str(); }
Probably good to overload a reference parm for ReadNum for cases where you need even less overhead.
template<typename t> void ReadNum(std::string src, t &ret) { std::istringstream s(src); s >> ret; }
That's not "more optimized", it's just a smaller vtable
A more worthwhile optimization:
template<typename t> t ReadNum(const std::string& src) { t ret; std::istringstream s(src); s >> ret; return ret; } template<typename t> std::string WriteNum(const t& src) { std::ostringstream ret; s << src; return s.str(); }
That's not "more optimized", it's just a smaller vtable
If it wasn't more optimized why would it exist?
Well, I got my problem resolved:
On all Intel (PC) computers, nothing to do.
I test the following:
On both the output value is 8 meaning that the size is the same.
On Intel bytes are ordered as following:
od -cx test
0000000 D 027 A T 373 ! \t @
1744 5441 21fb 4009
0000010
On SUN this is the following:
0000000 @ \t ! 373 T A 027 D
4009 21fb 5441 1744
0000010
So basically we can see that we should swap bytes by pack of two from start to end.
So basically we can see that we should swap bytes from start to end.

Thanks to all !
Cookies time !
EDIT: WTF ! I did as you said in my test code (getting the double value when opening an intel file on a sun ) And I really dunno why I write a so silly mistake. Thanks for pointing it out, orz.
So basically we can see that we should swap bytes by pack of two from start to end.
Nope. You should reverse in units of individual bytes, not sets of 2 bytes. The reason why you're seeing it in sets of 2 bytes is because you're printing them as 2-byte values, and the different endianness then hides the sub-2-byte ordering stuff. When changing endianness on any modern computer, the correct method is to reverse order in 1 byte units.
Fixed !
If it wasn't more optimized why would it exist?
If feet aren't meters why do they exist?
If feet aren't meters why do they exist?
Because the geniuses who designed C++ didn't create the foot or the meter.
Do you actually know the details of how stringstream, istreamstream, and ostringstream work? What about stringbuf?
stringstream, istringstream, and ostringstream all use stringbuf internally. It's the same class.
Do you actually know the details of how stringstream, istreamstream, and ostringstream work? What about stringbuf?
Yes sir.
Please either rephrase your original statement, support it, retract it or just stop posting.
You've given me so many options...
Anyway, my point that supported it fairly solidly was that the designers of C++ (lets make an acronym form them, how about Good Old [C++] DesierS) put a whole lot of thought into every bit of C++.
If the GODS thought that there should be an istringstream and an ostringstream class as opposed to just a single stringstream class then the GODS must of had a good reason. I don't question the GODS' purpose in this and yet I accept that the GODS are all knowing (in the domain of C++) and therefore I embrace and accept the istringstream into my life.
Fair enough. My point is that istringstream isn't any faster than stringstream, it simply has a smaller vtable.