使用并集将双精度转换为十六进制再转换为双精度

Converting from double to hexadecimal back to double using union

本文关键字:双精度 转换 十六进制      更新时间:2023-10-16

我甚至不确定我的标题是否准确,但对于我的项目,我需要取一个双精度并将其转换为十六进制,然后将其转换回双精度。但为了做到这一点,我想我需要让运营商<lt;然后我才能输出答案。这是我到目前为止所做的,但我得到提示"没有操作员"<lt;"匹配这些操作数">有人能告诉我应该如何重载<lt;操作员在主体中?非常感谢。

#include <iostream>
#include <iomanip>
#include <cstdint>
using namespace std;
void out_char_as_hex(int c)
{
cout << hex << setw(2) << setfill('0') << c;
}

int main()
{
union { double d; uint64_t u; } tmp;
double x = -0.15625;
tmp.d = x;
cout << out_char_as_hex(tmp.d) << endl;
return 0;
}

如果这有帮助的话,那就是"如果x是double类型的变量,它的二进制表示可以被重新解释为64位整数,它可以被精确地表示。要做到这一点,你可以获得double类型变量的内存地址,然后重新解释并将其转换为64位int指针,或者使用并集。为了使文本表示更紧凑,我们使用16进制例如,双位数-0.15625应保存为16个字符bfc4000000000000的序列(参见DemoHex.cpp中的示例,使用并集)。读取时,您需要读取整数以十六进制格式保存,并将其重新解释为双精度。您需要修改运算符<lt;双人间并实现操作员过载>>">

这是一个不使用并集的版本,而是将位模式从double复制到uint64_t

假设此位模式对整数有效,则复制也应该有效。它也产生了预期的产出。

#include <iostream>
#include <iomanip>
#include <cstdint>
using namespace std;
void out_char_as_hex(std::uint64_t c)
{
cout << hex << setw(16) << setfill('0') << c << endl;
}

int main()
{
uint64_t u;
double x = -0.15625;
std::memcpy(&u, &x, sizeof(u));
out_char_as_hex(u);
return 0;
}

然而,这并不是教授所要求的解决方案,因此可能是"错误的"。

如果转换只是为了打印,则不需要重载任何运算符。使用io操作器"std::hexfoat",您可以以十六进制打印浮点值。

根据你的示例代码和解释,我认为你正在尝试做如下

#include <iostream>
#include <iomanip>
union test
{
double x;
uint64_t y;
};
// Insertion operator is overloaded to take union and 
// print uint64_t value from it.  
std::ostream & operator << (std::ostream &out, const test &t)
{
out << std::hex << std::setw(50) << std::setfill('0') << t.y;
return out;
}
int main()
{
test t;
t.x = -0.15625;
std::cout << t << std::endl;    
return 0;
}

这里打印的是一个位模式,用于在内存中存储浮点数(符号位、指数和尾数)。

更新:上面的代码将导致未定义的行为,因为我们没有阅读最近编写的成员(参考:http://en.cppreference.com/w/cpp/language/union)

这里有一种不使用并集的替代方法。

#include <iostream>
#include <iomanip>
struct test
{
double x;
};
std::ostream & operator << (std::ostream &out, test &t)
{
uint64_t *y = reinterpret_cast<uint64_t *>(&t.x);
out << std::hex << std::setw(50) << std::setfill('0') << *y;
return out;
}
int main()
{
test t;
t.x = -0.15625;
std::cout << t << std::endl;
return 0;
}