2009-12-06 116 views
3

我有一個無符號的長整數值,它代表使用IEEE-754格式的浮點數。在C++中以flo​​at方式打印出來最快的方法是什麼?如何輸出IEEE-754格式的整數作爲浮點數

我知道一種方法,但我想知道是否有一個方便的C++實用程序會更好。的,我知道的方式

例子是:

union 
{ 
    unsigned long ul; 
    float f; 
} u; 

u.ul = 1084227584; // in HEX, this is 0x40A00000 

cout << "float value is: " << u.f << endl; 

(這會打印出「浮動值爲:5」)

回答

6

您提出的聯合方法是大多數人會採用的常用方法。然而,它在技術上在C/C++中用未定義的行爲從聯合中讀取不同於最近編寫的聯合成員。儘管如此,它在幾乎所有的編譯器中都得到了很好的支持。

鑄造指針,如Jon Skeet suggested,是一個壞主意 - 違反C.一個積極的優化編譯器的strict aliasing規則將產生不正確的代碼,這一點,因爲它假定的類型unsigned long *float *永遠互爲別名指針。

最正確的方式,在符合標準的條款(即不調用不確定的行爲),是通過char*投,因爲嚴格別名規則允許char*指針引用任何其他類型的指針:

unsigned long ul = 0x40A00000; 
float f; 
char *pul = (char *)&ul; // ok, char* can alias any type 
char *pf = (char *)&f; // ok, char* can alias any type 
memcpy(pf, pul, sizeof(float)); 

雖然老實說,我只想用union方法去。從上面的cellperformance.com鏈接:

這是一個非常普遍的習慣用語,並得到所有主要編譯器的支持。實際上,以任何順序閱讀和寫給工會的任何成員都是可以接受的做法。

+0

哇,我沒有意識到混疊會導致問題。感謝分享! – 2009-12-07 04:57:34

+0

用void *而不是char *可以接受嗎? – 2009-12-07 04:58:19

+1

'float'不能保證表示爲IEEE-754,所以使用任何形式的強制轉換將具有IEEE754的字節數組轉換爲浮點數仍然未定義。 – 2013-04-04 03:38:12

3

編輯:我以前認爲這「只是討厭」,但它結果比我想象的更糟糕 - 請參閱評論以獲取詳細信息。我不推薦這種方法,但我要離開這裏記錄的可能性


您可以使用指針(和警告!):

long ul = 1084227584; 
float* fp = (float*) &ul; 
float f = *fp; 

(這可以被濃縮成一條線,但我認爲它不會更清楚。)

基本上和你的工會一樣......除非你確定所涉及的類型的大小,否則它們同樣不可行。

如果您的平臺支持它們,您應該使用整數和浮點類型的大小特定的類型名稱。

+0

實際上,無論大小如何,它都依賴於實現。這比聯合技巧好,這個技巧是未定義的,但仍然不好。 – 2009-12-06 20:27:00

+0

壞主意。這打破了C99嚴格的別名規則,並且一個積極的優化編譯器可能會產生不正確的結果。請參閱http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html。 – 2009-12-06 20:43:09

+0

謝謝 - 我認爲這很不愉快,但實際尺寸沒有問題時實際上可能不會破碎。編輯更清楚,謝謝。請讓我知道,如果你認爲這是一個壞主意,答案應該完全刪除 - 我很樂意承認。 – 2009-12-06 20:46:15

3

它只適用於sizeof(long)== sizeof(float)的32位機器或機器上。在現代機器上,你可能想用int來代替......而且如果你正在執行這個技巧,你真的必須小心。

3

我在想和Jon Skeet一樣的東西,但是他打敗了我。但是,我會比他做得更簡潔一點。

cout << "float value is: " << *((float *) &ulValue)) << endl; 

你得到的一個指針unsigned long類型,然後重新解釋,作爲一個指針浮動,然後取消引用指針浮動產生的浮點值。

由於您在C++中這樣做,使用reinterpret_cast而不是舊的C風格轉換更清晰。

cout << "float value is: " << *(reinterpret_cast<float *>(&ulValue)) << endl; 
1

swegi有正確的方向,但錯過了一個字符。正確的方法是

long l = 1084227584L 
float f = reinterpret_cast<float&>(l);