2013-02-18 62 views
3

我正在絞盡腦汁想弄清楚爲什麼這段代碼沒有得到正確的結果。我正在尋找浮點正負溢出/下溢級別的十六進制表示。本代碼是基於關閉此位點和Wikipedia entry浮點限制代碼不能產生正確的結果

7f7f FFFF≈3.4028234×10(最大單精度) - 從維基百科條目,對應於正溢出

下面的代碼:

#include <iostream> 
#include <cstdio> 
#include <cstdlib> 
#include <cmath> 

using namespace std; 

int main(void) { 

    float two = 2; 
    float twentyThree = 23; 
    float one27 = 127; 
    float one49 = 149; 


    float posOverflow, negOverflow, posUnderflow, negUnderflow; 

    posOverflow = two - (pow(two, -twentyThree) * pow(two, one27)); 
    negOverflow = -(two - (pow(two, one27) * pow(two, one27))); 


    negUnderflow = -pow(two, -one49); 
    posUnderflow = pow(two, -one49); 


    cout << "Positive overflow occurs when value greater than: " << hex << *(int*)&posOverflow << endl; 


    cout << "Neg overflow occurs when value less than: " << hex << *(int*)&negOverflow << endl; 


    cout << "Positive underflow occurs when value greater than: " << hex << *(int*)&posUnderflow << endl; 


    cout << "Neg overflow occurs when value greater than: " << hex << *(int*)&negUnderflow << endl; 

} 

的輸出是:

正發生溢出時VA略大於:當值大於7f800000 正溢時:當值小於發生f3800000 負片溢出1 負片溢出時發生值大於:80000001

爲了讓浮點的十六進制表示,我正在使用描述的方法here

爲什麼代碼不工作?我知道如果積極溢出= 7f7f ffff它會起作用。

+1

你應該使用'double'而不是'float'。 – 2013-02-18 03:19:11

+0

@LokiAstari你不能簡單地將'double'替換成這個代碼,所有的表達式都需要改變,因爲它們以不同的值溢出和下溢。另外,由於這段代碼的目的似乎是對IEEE浮點的更好的理解,我認爲'float'正是他應該使用的。 – 2013-02-18 03:58:40

回答

3

您表達的最高可表示正浮動是錯誤的。您鏈接的頁面使用(2-pow(2, -23)) * pow(2, 127),並且您有2 - (pow(2, -23) * pow(2, 127))。對於最小的可表示負浮標也是如此。

但是,您的下溢表達式看起來是正確的,對於它們的十六進制輸出也是如此。

請注意,posOverflownegOverflow只是+FLT_MAX-FLT_MAX。但請注意,您的posUnderflownegUnderflow實際上FLT_MIN(因爲它們是非標準,而FLT_MIN是最小的正正常浮動)。

+0

謝謝(非常尷尬,我沒有看到) – 2013-02-18 03:35:15

1

你的代碼假定整數有大小爲float同你可能想沿着線的東西(所以做所有,但一些你的鏈接頁面上的帖子,順便說一句。):

for (size_t s = 0; s < sizeof(myVar); ++s) { 
    unsigned char *byte = reinterpret_cast<unsigned char*>(myVar)[s]; 
    //sth byte is byte 
} 

也就是說,類似於該頁面上的模板代碼。

您的編譯器可能沒有使用這些特定的IEEE 754類型。你需要檢查它的文檔。

此外,請考慮使用std::numeric_limits<float>.min()/max()cfloatFLT_用於確定其中某些值的常量。

+1

'*(int *)&'假設'float'與'int'的大小相同(並且編譯器會使嚴格的別名違規滑動)。你的代碼假定機器的字節順序(或者你會嘗試使用字節)。所有「正確」的方法都是依賴於體系結構或編譯器。 – 2013-02-18 03:27:57

2

浮點隨着數字變大而失去精度。當您向其中添加2時,數量級2 不會更改。

除此之外,我並沒有真正遵循你的代碼。用單詞拼出數字使我很難閱讀。

這是標準的方式來獲得你的機器的浮點限制:

#include <limits> 
#include <iostream> 
#include <iomanip> 

std::ostream &show_float(std::ostream &s, float f) { 
    s << f << " = "; 
    std::ostream s_hex(s.rdbuf()); 
    s_hex << std::hex << std::setfill('0'); 
    for (char const *c = reinterpret_cast< char const * >(& f); 
      c != reinterpret_cast< char const * >(& f + 1); 
      ++ c) { 
     s_hex << std::setw(2) << (static_cast< unsigned int >(* c) & 0xff); 
    } 
    return s; 
} 

int main() { 
    std::cout << std::hex; 
    std::cout << "Positive overflow occurs when value greater than: "; 
    show_float(std::cout, std::numeric_limits<float>::max()) << '\n'; 
    std::cout << "Neg overflow occurs when value less than: "; 
    show_float(std::cout, - std::numeric_limits<float>::max()) << '\n'; 
    std::cout << "Positive underflow occurs when value less than: "; 
    show_float(std::cout, std::numeric_limits<float>::denormal_min()) << '\n'; 
    std::cout << "Neg underflow occurs when value greater than: "; 
    show_float(std::cout, - std::numeric_limits<float>::min()) << '\n'; 
} 

輸出:

Positive overflow occurs when value greater than: 3.40282e+38 = ffff7f7f 
Neg overflow occurs when value less than: -3.40282e+38 = ffff7fff 
Positive underflow occurs when value less than: 1.17549e-38 = 00008000 
Neg underflow occurs when value greater than: -1.17549e-38 = 00008080 

輸出取決於機器的字節序。這裏的字節由於小端順序而被顛倒過來。請注意,在這種情況下,「下溢」不是一個災難性的零結果,而只是反規範化,逐漸降低精度。 (不過,這可能會對性能造成災難性影響)。您也可以檢查生產1.4013e-45 = 01000000numeric_limits<float>::denorm_min()

+0

'numeric_limits :: min()'是最小的可表示*標準化*浮動,而不是最小的可表示的浮動。所以你實際上在這些情況下找到與鏈接文章不同的值。 – 2013-02-18 03:34:21

+0

@JohnCalsbeek是的,正在編輯,因爲你張貼:)現在修復。 – Potatoswatter 2013-02-18 03:36:36

相關問題