我试图将十六进制字符串转换为double值,其中一些值为负值。 This answer适用于正双十六进制字符串,但是当double为负时,我得到一个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
答案 0 :(得分:2)
当然stoll
会在输入std::out_of_range exception
上引发"bfb999999999999a"
,因为0xbfb999999999999a > LLONG_MAX
。如果您使用stoull
,那么一切都很顺利,因为0xbfb999999999999a <= ULLONG_MAX
。
答案 1 :(得分:1)
您可以将十六进制字符串传递给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;
}