【问题标题】:Convert Double to Hex String?将双精度转换为十六进制字符串?
【发布时间】:2014-05-05 07:34:33
【问题描述】:

在我的项目中,我将一个双变量读取为十六进制并将其加载到字符串中。

我需要将该十六进制字符串转换为双精度数。我目前使用这个:

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

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

    return value.d;
}

当我这样做时:

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

输出为 10.6259。不准确,但我没问题。

然后用户可以将该号码编辑为他们想要的任何内容。如何将他们的数字转换回十六进制表示?

感谢您的宝贵时间。

【问题讨论】:

  • snprintf 与您工会的第 i 个成员的 %llx?
  • ?对不起,我不明白你的评论。我只在 Qt 中编写过 C++
  • 这在什么意义上不准确?
  • 您还需要解决字节顺序问题。
  • @mc360pro 正如 David Hefferman 所指出的,我越来越担心字节顺序问题。这当然完全取决于十六进制字符串的目的是什么。上面的编码函数和下面的解码函数提供了双精度的 a 表示,但这种表示取决于硬件的字节顺序,它可能与内存表示不匹配(例如,按内存位置排序)。 . 只要您在同一台机器上进行编码和解码并且不对十六进制字符串进行任何进一步处理就可以了....但如果不是,您将面临问题。

标签: c++ floating-point hex double


【解决方案1】:

虽然 sstream 是一个很好的答案...关于在多线程程序中使用流的 concernshere

与 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;
}

编辑(使用 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;
}

注意...我并不是说 std::ostringstream 不起作用。它在内存安全方面当然具有更好的属性(因为 snprintf 比 sprintf 具有更好的属性)......但是请注意(至少在 STL 的某些实现中)在多线程程序中可能会导致过度锁定。

【讨论】:

  • -1 除非你能支持这些神秘的“担忧”
  • snprintf 标识符未找到。
  • 您必须包含cstdio。为什么要谈论 C++,不是吗?
  • @mc360pro 最后一条评论很粗鲁。请不要立即放弃。你以前肯定遇到过包含文件。
  • 是的,但是我正在使用 Qt 进行开发并且包含 cstdio 并没有解决问题。
【解决方案2】:

当你像这样使用union时,注意不可移植(不符合C++标准)。

有一个很好的讨论:CppCon 2019: Timur Doumler “Type punning in modern C++”

一致的解决方案可能是:

#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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-13
    • 2019-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-14
    相关资源
    最近更新 更多