2013-02-18 66 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