Thanks for your posts :)
I've left and commented out the unsuccessful "save as hexfloat string" code, incase someone can get it working.
I've also left and commented out the usual "save as high-precision decimal & exponent string" code, as a quick fallback incase "save via int" doesn't work on other platforms. It may work as it is, but might require an sprintf format specifier other than "%I32u" or "%I64u" (safest to use unsigned I think, because something odd might happen with the sign bit!)
I've allowed for float and double to each be either 4 or 8 bytes. Won't be difficult to extend to include other sizes if necessary.
I'm going to keep memcpy for now, because I've read a few things about it being the only way to guarantee that the bits are preserved, and it's finally working :)
Code: Select all
std::string DoubleToStr(double val)
{
// Exact representation (but not human readable).
static_assert(sizeof(double) == 4 || sizeof(double) == 8, "double isn't 4 or 8 bytes");
if (sizeof(double) == 4)
{
uint32_t intVal;
memcpy(&intVal, &val, 4);
char str[16];
std::sprintf(str, "%I32u", intVal);
return str;
}
else // sizeof(double) == 8
{
uint64_t intVal;
memcpy(&intVal, &val, 8);
char str[32];
std::sprintf(str, "%I64u", intVal);
return str;
}
}
double StrToDouble(std::string str)
{
// Exact representation (but not human readable).
static_assert(sizeof(double) == 4 || sizeof(double) == 8, "double isn't 4 or 8 bytes");
if (sizeof(double) == 4)
{
uint32_t intVal;
std::sscanf(str.c_str(), "%I32u", &intVal);
double val;
memcpy(&val, &intVal, 4);
return val;
}
else // sizeof(double) == 8
{
uint64_t intVal;
std::sscanf(str.c_str(), "%I64u", &intVal);
double val;
memcpy(&val, &intVal, 8);
return val;
}
}
I'm using std::sprintf and std::sscanf. I didn't realise they existed 'til the other day. The documentation for the default sscanf says "%a" is not supported, which is why I went to the standard lib versions. However, the hexfloat didn't work for std::sscanf either. Are the std:: functions always the same across all platforms?
The documentation for std::sscanf doesn't mention the "%I32u" or "%I64u", but rather "%lu" and "%llu" (which also work) so if need be, a platform #ifdef can be used to select the one that works.