3

このコードで正しい結果が得られない理由を突き止めようと頭を悩ませています。浮動小数点の正および負のオーバーフロー/アンダーフロー レベルの 16 進数表現を探しています。コードは、このサイトとウィキペディアのエントリに基づいています。

7f7f ffff ≈ 3.4028234 × 10 38 (最大単精度) -- ウィキペディアのエントリから、正のオーバーフローに対応

コードは次のとおりです。

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

}

出力は次のとおりです。

値がより大きい場合に正のオーバーフローが発生:f3800000 値がより小さい場合に負のオーバーフローが発生7f800000 : 値がより大きい場合に正のアンダーフローが発生: 値がより大きい場合1 に負のオーバーフローが発生:80000001

浮動小数点の 16 進数表現を取得するために、ここで説明する方法を使用しています。

コードが機能しないのはなぜですか? 正のオーバーフロー = の場合に機能することはわかっています7f7f ffff

4

3 に答える 3

3

表現可能な最高の正の浮動小数点数の表現が間違っています。リンクしたページは を使用しており(2-pow(2, -23)) * pow(2, 127)、 を持ってい2 - (pow(2, -23) * pow(2, 127))ます。最小の表現可能な負の浮動小数点数についても同様です。

ただし、アンダーフロー式は正しく見え、それらの 16 進出力も同様です。

posOverflownegOverflowは単に+FLT_MAXとであることに注意してください-FLT_MAX。ただし、posUnderflowandnegUnderflowは実際にはより小さいFLT_MINことに注意してください(これらは非正規でありFLT_MIN、最小の正の正規浮動小数点数であるため)。

于 2013-02-18T03:23:28.793 に答える
2

浮動小数点は、数値が大きくなるにつれて精度が低下します。マグニチュード 2 127の数は、 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

出力はマシンのエンディアンに依存します。ここでは、リトル エンディアン順のため、バイトが逆になっています。

この場合の「アンダーフロー」は壊滅的なゼロの結果ではなく、精度を徐々に低下させる単なる非正規化であることに注意してください。(ただし、パフォーマンスに壊滅的な影響を与える可能性があります。)numeric_limits< float >::denorm_min()どちらが を生成するかを確認することもできます1.4013e-45 = 01000000

于 2013-02-18T03:30:36.853 に答える
1

あなたのコードは、整数がフロートと同じサイズであると想定しています(リンクしたページのいくつかの投稿を除いてすべてそうです)。おそらく、次の行に沿って何かが必要です。

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()または定数を使用することを検討してください。cfloat FLT_

于 2013-02-18T03:03:12.327 に答える