I have a string in 32-bit IEEE-754 hex format and I need the decimal value for a double, long double, float or whatever. For example, I have: 42140BB4, which is 37.01142883300781. I see examples online in places like these: http://babbage.cs.qc.edu/IEEE-754/32bit.html http://www.h-schmidt.net/FloatApplet/IEEE754.html I'm sure there's a way to do it in one line with a standard C++ library, but I can't get the bugger to work... Anyone have any ideas?
Might the following work? (I can't test it where I'm at.) ... char *end; char* s = "0xFF0A003C"; float f = strtof(s, end); // should test end for null to see if conversion was ok cout << f; ... see also strtod(), strtold() I hope that's helpful...
It's not quite right, but it points me in a useful direction, I think. Thanks. Code: int main() { char *end; char* paladin_char = "0xFF0A003C"; char* spider_char_one = "42140bb4"; char* spider_char_two = "42141e4c"; float paladin_float = strtof(paladin_char, &end); float spider_float_one = strtof(spider_char_one, &end); float spider_float_two = strtof(spider_char_two, &end); cout << paladin_char << "\t->\t" << paladin_float << "\n"; cout << spider_char_one << "\t->\t" << spider_float_one << "\n"; cout << spider_char_two << "\t->\t" << spider_float_two << "\n"; return(0); } gives: 0xFF0A003C -> 4.27885e+09 42140bb4 -> 42140 42141e4c -> 4.2141e+08
Cheap way out! But that's always the best way realistically don't reinvent the wheel when you dont have to. However, if you want to roll your own you need to understand the spec: http://en.wikipedia.org/wiki/Single_precision I remember I had a similar problem back in school, had to be solved in Sparc assembly using only integer operations but the concepts can be carried over. Basically the idea is you use a bit mask to do a bitwise AND on the number (to zero out the leading digits you don't care about), then you shift right until you get a regular old integer for the sign, exponent, and significand portions of the number, then you can manually figure out the value. The same concepts are easier to apply to a string than a bunch of bits as well. But you should really go for paladins method unless what you are doing is a learning exercise or something
Code: string initial_result=exec("nc -i 2 mds-4c-xx02 2103 < get_data_command | od -t xC"); ///////////////////////////// string temp_buff; stringstream temp_ss(initial_result); vector<string> temp_v; while (temp_ss >> temp_buff) temp_v.push_back(temp_buff); string trimmed_result="0x"+temp_v.at(6)+temp_v.at(7)+temp_v.at(4)+temp_v.at(5); ///////////////////////////// const char *Input=trimmed_result.c_str(); unsigned long unsigned_long = strtoul (Input,NULL,0); union { unsigned long ul; float f;} u; u.ul = unsigned_long; float final_result = u.f; printf("%f\n",final_result); This works.
Have you verified that works? I'm a little rusty with union, but reinterpreting the bits of a long integer into a float doesn't seem like that should produce the right answer... edit: unless, of course, you knew that the hex you started with was created in the reverse operation (float -> unsigned long).
It'll work, at least in a 32-bit runtime, even if it is slightly abusive of the type system. Edit, then again, I did do this once: //I have a bitfield bf which is a typedef'd int char ar[4] = *bf; char a = ar[0]; char b = ar[1]; char c = ar[2]; char d = ar[3]; instead of char a = bf >> 24; char b = bf >> 16; char c = bf >> 8; char d = (char)bf;
Of course, they're like London buses. As soon as one solution comes along, another one pops up, just to make you look stupid. Thanks again, guys. Code: #include <stdio.h> union ieee754 { int hex; float flt; }; int main () { int h1 = 0x42141cd7; float f1 = *((float*)&h1); float f2=37.028164; int h2= *((int*)&f2); printf("IEEE Hex: 0x%8.8x -> Float: %f\n", h1, f1); printf("IEEE Hex: 0x%8.8x <- Float: %f\n", h2, f2); /////////////////////////// ieee754 var1; ieee754 var2; var1.hex = 0x42141cd7; var2.flt = 37.028164; printf("IEEE Hex: 0x%8.8x -> Float: %f\n", var1.hex, var1.flt); printf("IEEE Hex: 0x%8.8x <- Float: %f\n", var2.hex, var2.flt); return 0; }
^Either of those two are much better than the previous one, as they're 64-bit safe. This one's not 16-bit safe, but I think that'll be a rarer case unless you're doing embedded processor programming.
^Aye. In gcc-64, ints are 32 bits and longs are 64 bits. This is a change from the 16->32 bit transition, where both ints and longs became 32 bits from 16 bits. The other thing you can use, if your library supports it, is the u_int32/uint32/uint_32 type, which is typedefed in several #ifdef blocks so that no matter what platform you're on, you always get a 32-bit wide data type if the hardware supports it.