【问题标题】:Converting hex string to negative double将十六进制字符串转换为负双精度
【发布时间】:2014-12-10 04:58:11
【问题描述】:

我正在尝试将十六进制字符串转换为双精度值,其中一些值为负数。 This answer 适用于正双十六进制字符串,但当双精度为负时,我得到一个 std::out_of_range 异常。这是为什么?有没有办法绕过它?

我也尝试对 stringstream 做同样的事情,这对正负十六进制字符串都适用。所以总是有这样的解决方案,但对我来说,联合方法看起来更优雅一些。我猜是口味问题。

示例代码:

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


int main()
{
    std::string str1("3fb999999999999a"); //  0.1
    std::string str2("bfb999999999999a"); // -0.1


    // ******************************
    // UNION
    // ******************************
    union uint64double
    {
        unsigned long long i;
        double    d;
    };

    uint64double val1;
    val1.i = std::stoll(str1, nullptr, 16);

    uint64double val2;
    val2.i = std::stoll(str2, nullptr, 16);     // This throws std::out_of_range exception

    const int w = 18;

    std::cout << "USING UNION" << std::endl;
    std::cout << std::setw(w) << "HEX" << std::setw(w) << "DOUBLE" << std::endl;
    std::cout << std::setw(w) << str1 << std::setw(w) << val1.d << std::endl;
    std::cout << std::setw(w) << str2 << std::setw(w) << val2.d << std::endl;

    std::cout << std::endl;


    // ******************************
    // STRINGSTREAM
    // ******************************
    unsigned long long i1;
    std::stringstream ss;
    ss << std::hex << str1;
    ss >> i1;
    double d1(reinterpret_cast<double&>(i1));

    unsigned long long i2;
    ss.clear();
    ss << std::hex << str2;
    ss >> i2;
    double d2(reinterpret_cast<double&>(i2));

    std::cout << "USING STRINGSTREAM" << std::endl;
    std::cout << std::setw(w) << "HEX" << std::setw(w) << "DOUBLE" << std::endl;
    std::cout << std::setw(w) << str1 << std::setw(w) << d1 << std::endl;
    std::cout << std::setw(w) << str2 << std::setw(w) << d2 << std::endl;

    std::cout << std::endl;

    return 0;
}

输出:

USING UNION
           HEX            DOUBLE
  3fb999999999999a               0.1
  bfb999999999999a           1.#QNAN

USING STRINGSTREAM
               HEX            DOUBLE
  3fb999999999999a               0.1
  bfb999999999999a              -0.1

我正在使用 VS2012

【问题讨论】:

    标签: c++ string visual-studio-2012


    【解决方案1】:

    当然stoll 会在输入"bfb999999999999a" 时抛出std::out_of_range exception,因为0xbfb999999999999a &gt; LLONG_MAX。如果你改用stoull,一切都会很好,因为0xbfb999999999999a &lt;= ULLONG_MAX

    【讨论】:

      【解决方案2】:

      您可以将十六进制字符串传递给stringstream 构造函数以对其进行清理。你的std::hex 放错地方了。 std::hex 告诉流将输入视为十六进制值,而不仅仅是一堆字符。

      我也会将此功能放在它自己的函数中,以使其更简洁:

      #include <string>
      #include <iostream>
      #include <iomanip>
      #include <sstream>
      
      double hexToDouble(const std::string& hex)
      {
          double d = 0;
          std::stringstream ss(hex);
          ss >> std::hex >> reinterpret_cast<uint64_t&>(d); // I feel dirty
          return d;
      }
      
      int main()
      {
          std::string str1("3fb999999999999a"); //  0.1
          std::string str2("bfb999999999999a"); // -0.1
      
          std::cout << str1 << ' ' << hexToDouble(str1) << std::endl;
          std::cout << str2 << ' ' << hexToDouble(str2) << std::endl;
      
          return 0;
      }
      

      【讨论】:

      • 好建议。谢谢!
      猜你喜欢
      • 2014-05-05
      • 2019-08-13
      • 2019-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-14
      相关资源
      最近更新 更多