2013-02-18 2 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; 

} 

выход:

Положительное переполнение возникает, когда в LUE больше: f3800000 переполнения отра происходит, когда значение меньше, чем: происходит 7f800000 Положительного опустошение, когда значение больше: происходит 1 переполнения отра, когда значение больше: 80000001

Чтобы получить шестнадцатеричное представление с плавающей точкой , Я использую метод, описанный here:

Почему код не работает? Я знаю, что это сработает, если положительное переполнение = 7f7f ffff.

+1

Возможно, вы должны использовать 'double', а не' float'. –

+0

@LokiAstari Вы не можете просто заменить 'double' на этот код, все соответствующие выражения должны будут измениться, поскольку они переполняются и переполняются с разными значениями. Кроме того, поскольку цель этого кода, по-видимому, является лучшим пониманием плавающей точки IEEE, я бы сказал, что 'float' - это именно то, что он должен использовать. –

ответ

3

Ваше выражение для наивысшего представляемого положительного поплавка является неправильным. На странице, которую вы связываете, используется (2-pow(2, -23)) * pow(2, 127), и у вас есть 2 - (pow(2, -23) * pow(2, 127)). Аналогично для наименьшего представляемого отрицательного поплавка.

Ваши выражения нижнего уровня выглядят правильно, однако, и для них шестнадцатеричные выходы.

Обратите внимание, что posOverflow и negOverflow - это просто +FLT_MAX и -FLT_MAX. Но обратите внимание, что ваш posUnderflow и negUnderflow фактически меньше, чемFLT_MIN (потому что они denormal и FLT_MIN является наименьшим положительным нормальным поплавок).

+0

спасибо (очень смущен, что я этого не видел) –

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() или cfloatFLT_ константы для определения некоторых из этих значений.

+1

'* (int *) &' предполагает, что 'float' имеет тот же размер, что и' int' (и что компилятор допустит слабые нарушения сглаживания). Ваш код предполагает конечность устройства (или он попытается использовать байты). Все «правильные» способы сделать это зависят от архитектуры или компилятора. –

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 

Выход зависит от байтов машины. Здесь байты обращаются из-за мало-конечного порядка.

Примечание: «нижний поток» в этом случае не является катастрофическим нулевым результатом, а просто денормализацией, которая постепенно снижает точность. (Это может быть катастрофическим для производительности.) Вы также можете проверить numeric_limits<float>::denorm_min(), который производит 1.4013e-45 = 01000000.

+0

'numeric_limits :: min()' - наименьший представляемый * нормализованный * float, а не наименьший представляемый поплавок. Таким образом, вы фактически находите разные ценности, чем связанная статья в этих случаях. –

+0

@JohnCalsbeek Да, редактировалось, когда вы разместили это :) исправлено сейчас. – Potatoswatter

Смежные вопросы