2017-10-10 91 views
0

我甚至不确定我的标题是否准确,但对于我的项目,我需要使用double并将其转换为十六进制,然后将其转换为double。但为了做到这一点,我想在输出答案之前,我需要超载运营商< <。这是我到目前为止,但我得到的提示,“没有运营商”< <“匹配这些操作数”>有人可以请指出我应该如何超载在主要运算符<的正确方向吗?谢谢!使用union将double转换为double使用

#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中的示例, ,它们使用联合)。读取时,需要读取以十六进制格式保存的整数 ,并将其重新解释为双倍。 您需要修改th双 操作< <电子执行和落实运营>>超负荷”

+5

你“不能”使用联合。在C++中通过联合打字是非法的。 – NathanOliver

+0

也许我错过了一些东西,但这个问题对我没有意义。没有浮点值的十六进制表示。你能写一些预期的输入/输出吗? – AndyG

+0

嗨Nathan感谢您的回复。我所拥有的项目要求我使用union函数,因此prof要求我们重载<<运算符以使其运行。对此有何想法? – Bert

回答

2

这是不使用工会的一个版本,但是从doubleuint64_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; 
} 

但是,这不是教授要求的解决方案,所以可能是“错误的”。

+0

我从来没有听说过整数的无效位模式,我知道每个模式从0x0000 ...到0xFFFF。小心解释?或者你的意思是模式不适合给定的整数? – stefaanv

+0

@Bo Persson感谢您的帮助!但我不认为我能够使用您的解决方案 – Bert

+1

@stefaanv - There曾经是奇数机器,其中不是所有*位模式都是有效值,有些无效值可能会产生陷阱,但这些机器都不会有'uint64_t'类型(只是想抢占可能未定义的注释在这里也是如此) –

0

如果转换仅用于打印,则不需要超载任何操作员。使用io操纵器'std :: hexfloat'可以打印十六进制的浮点数。

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

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

无论在这里印刷是用于存储浮点数的内存(符号位的位模式,指数和尾数)。

UPDATE: 上面的代码将导致进入未定义的行为,因为我们没有从最近写入的成员(参考: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; 
} 
+0

Hi Nyemul,谢谢你的h ELP!它似乎是我需要的东西。我会尽力消化它!为了澄清,这意味着如果只需要打印,则不需要“<<”运算符?但我认为我们需要进行转换并存储它们。可能这就是为什么我们需要超载?非常感谢! – Bert

+0

您不必为插入(<<)操作符而重载或转换。如果您希望运营商使用用户定义的类型进行更多操作,则需要运营商重载。在内部,所有数字都以二进制形式存储,因此您打算如何存储十六进制数字? – nyemul

+0

此答案与之前已删除的答案共享问题。您正在写信给一位工会成员,然后从另一位成员那里读取。在C中,这是很好定义的,但在C++中它是正式的未定义的。来自http://en.cppreference.com/w/cpp/language/union *“这是未定义的行为,可以从最近没有编写过的联盟成员中读取,许多编译器将其作为非标准语言扩展,读取工会不活跃成员的能力。“*所以它可能会工作,但不是标准的。这也是为什么我写了一个非工会的答案。 –

相关问题