2017-10-10 41 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 *「這是未定義的行爲,可以從最近沒有編寫過的聯盟成員中讀取,許多編譯器將其作爲非標準語言擴展,讀取工會不活躍成員的能力。「*所以它可能會工作,但不是標準的。這也是爲什麼我寫了一個非工會的答案。 –