Что должно возвращать frexp(FLT_MAX, )?

Каким должен быть результат следующей программы?

#include <stdio.h>
#include <math.h>
#include <float.h>

int main() {
    int exp;
    float mant = frexp(FLT_MAX, &exp);
    printf("frexp(%a) = {%f, %d}\n", FLT_MAX, mant, exp);
    return 0;
}

В моей системе Linux amd64 с glibc печатается:

frexp(0x1.fffffep+127) = {1.000000, 128}

Из статьи Википедии IEEE 754 я вижу, что "Самое большое нормализованное число" имеет показатель степени 127. Я также вижу, что единственными значениями с показателем степени 128 являются ± Infinity и NaN.

Из справочной страницы frexp я понимаю, что frexp() должна возвращать значение в диапазоне [ 0,5, 1,0) (то есть исключая 1,0).

И мантисса, и показатель экспоненты кажутся неверными на основе этих фрагментов информации.

Зная, что делает frexp(), и значение FLT_MAX (= (2 - 2^-23) * 2^127) говорит мне, что {1.0, 128} действительно очень близко к правильному ответу, поскольку (2 - 2^- 23) очень близко к 2.

Так что же должно возвращать frexp(FLT_MAX,...)?


person mattst88    schedule 17.08.2013    source источник
comment
(0.5, 1.0] должно быть [0.5, 1.0) кстати :)   -  person 0decimal0    schedule 17.08.2013
comment
Это не должно быть вопросом того, что возвращает frexp(), но какую точность следует использовать, как вы сами сказали Зная, что делает frexp(), и значение FLT_MAX (= (2 - 2 ^ -23) * 2 ^ 127) говорит мне кажется, что {1.0, 128} действительно очень близко к правильному ответу, поскольку (2 - 2^-23) очень близко к 2 , это означает, что вы теряете точность. Попробуйте double вместо float .   -  person 0decimal0    schedule 17.08.2013
comment
Для поплавков одинарной точности вы должны использовать frexpf вместо frexp.   -  person Giovanni Cerretani    schedule 21.11.2018


Ответы (1)


Я благодарю вас за печать FLT_MAX в формате %a, чтобы вы могли видеть, что на самом деле представляет собой значение, а не то, как его печатает %f. Так почему бы не сделать это и для значения mant?

frexp(0x1.fffffep+127) = {0x1.fffffep-1, 128}

Такой результат мне кажется неудивительным. (Обратите внимание, что показатель степени в представлении IEEE-754 основан на мантиссе в диапазоне [1.0, 2.0), тогда как frexp генерирует мантисса в диапазоне [0.5, 1.0). Таким образом, максимальный показатель степени frexp на единицу выше.)

Мораль: Никогда не путайте значение с плавающей запятой с тем, как оно выглядит.

person rici    schedule 17.08.2013
comment
Действительно, вы совершенно правы. Я должен был напечатать оба числа с плавающей запятой с %a, чтобы увидеть, что происходит на самом деле. - person mattst88; 17.08.2013