Question

In my project, I read a double variable as hex and load it into a string.

I need to convert that hex string to a double number. I currently use this:

double hexstr2double(const std::string& hexstr)
{
    union
    {
        long long i;
        double    d;
    } value;

    value.i = std::stoll(hexstr, nullptr, 16);

    return value.d;
}

When I do this:

qDebug() << hexstr2double("402540798D23092A");

The output is 10.6259. Not exact, but I'm fine with it.

The user then gets to edit that number to anything they want. How can I convert their number back to Hexadecimal representation?

Thanks for your time.

Was it helpful?

Solution

Although sstream is a fine answer... there are concerns and here about the use of streams in multithreaded programs.

similar solution with snprintf:

#include <iostream>
#include <cstdio>

double hexstr2double(const std::string& hexstr)
{
    union
    {
        long long i;
        double    d;
    } value;

    value.i = std::stoll(hexstr, nullptr, 16);

    return value.d;
}

std::string double2hexstr(double x) {

    union
    {
        long long i;
        double    d;
    } value;

   value.d = x;

   char buf[17];

   snprintf (buf,sizeof(buf),"%016llx",value.i);
   buf[16]=0; //make sure it is null terminated.

   return std::string(buf);

}

int main(int argc,char **argv) {
 double a=3.141592;
 std::string x=double2hexstr(a);
 double b=hexstr2double(x);

 std::cout << a << std::endl;
 std::cout << x << std::endl;
 std::cout << b << std::endl;
 return 0;
}

Edit (alternative version using std::ostringstream)

#include <iostream>
#include <sstream>
#include <iomanip>

double hexstr2double(const std::string& hexstr)
{
    union
    {
        long long i;
        double    d;
    } value;

    value.i = std::stoll(hexstr, nullptr, 16);

    return value.d;
}

std::string double2hexstr(double x) {

    union
    {
        long long i;
        double    d;
    } value;

   value.d = x;

   std::ostringstream buf;
   buf << std::hex << std::setfill('0') << std::setw(16) << value.i;

   return buf.str();

}

int main(int argc,char **argv) {
 double a=3.141592;
 std::string x=double2hexstr(a);
 double b=hexstr2double(x);

 std::cout << a << std::endl;
 std::cout << x << std::endl;
 std::cout << b << std::endl;
 return 0;
}

Note... I'm not saying that std::ostringstream does not work. It has certainly better properties regarding memory safety (as snprintf has better properties over sprintf)... However be aware that (at least in some implementations of STL) in a multithreaded program might lead to excesive locking.

OTHER TIPS

When you use union like this, be careful that is not portable (not conform to C++ standard).

There is a very talk about that : CppCon 2019: Timur Doumler “Type punning in modern C++”

A conform solution could be:

#include <iostream>
#include <cstdio>
#include <cstdint>
#include <cstring>

double hexstr2double(const std::string& hexstr) {
    uint64_t i = std::stoll(hexstr, nullptr, 16);
    double d;
    std::memcpy(&d,&i,8);
    return d;
}

std::string double2hexstr(double x) {
   uint64_t i;
   std::memcpy(&i,&x,8);

   char buf[17];
   snprintf (buf,sizeof(buf),"%016llx",i);
   buf[16]=0; //make sure it is null terminated.

   return std::string(buf);
}

int main(int argc,char **argv) {
 double a=3.141592;
 std::string x=double2hexstr(a);
 double b=hexstr2double(x);

 std::cout << a << std::endl;
 std::cout << x << std::endl;
 std::cout << b << std::endl;
 return 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top