我想模拟各种n位二进制浮点格式,每种格式都具有指定的e_max和e_min,并具有p位精度。我希望这些格式能够模拟次标准数字,忠于IEEE-754标准。
自然地,我的搜索使我进入了MPFR库,该库符合IEEE-754规范,并能够使用mpfr_subnormalize()函数支持次规范。但是,在使用mpfr_set_emin()mpfr_set_emax()正确设置启用了非正规功能的环境时,我遇到了一些困惑。我将使用IEEE double 作为示例格式,因为这是MPFR手册中使用的示例:
http://mpfr.loria.fr/mpfr-current/mpfr.html#index-mpfr_005fsubnormalize

mpfr_set_default_prec (53);
mpfr_set_emin (-1073); mpfr_set_emax (1024);
上面的代码来自上面链接中的MPFR手册-请注意,e_max和e_min都不等于double的期望值。这里,如double类型所期望的那样,将p设置为53,但是将e_max设置为1024,而不是1023的正确值,并且将e_min设置为-1073。远低于-1022的正确值。我知道将指数范围设置得过紧会导致MPFR中间计算中的上溢/下溢,但是我发现准确设置e_min对于确保正确的次正规数至关重要。太高或太低都会导致MPFR结果不正常(用mprf_subnormalize()更新)与相应的double结果不同。
我的问题是,应该如何确定将哪些值传递给mpfr_set_emax()和(尤其是mpfr_set_emin()),以保证指数范围为e_max和e_min的浮点格式的正确次正规行为?关于此事,似乎没有任何详细的文档或讨论。
非常感谢
詹姆士。
编辑30/07/16:这是一个小程序,它演示了单精度数字的e_max和e_min的选择。
#include <iostream>
#include <cmath>
#include <float.h>
#include <mpfr.h>

using namespace std;

int main (int argc, char *argv[]) {
    cout.precision(120);

    // IEEE-754 float emin and emax values don't work at all
    //mpfr_set_emin (-126);
    //mpfr_set_emax (127);

    // Not quite
    //mpfr_set_emin (-147);
    //mpfr_set_emax (128);

    // Not quite
    //mpfr_set_emin (-149);
    //mpfr_set_emax (128);

    // These float emin and emax values work in subnormal range
    mpfr_set_emin (-148);
    mpfr_set_emax (128);

    cout << "emin: " << mpfr_get_emin() << "    emax: " << mpfr_get_emax() << endl;

    float f = FLT_MIN;
    for (int i = 0; i < 3; i++) f = nextafterf(f, INFINITY);

    mpfr_t m;
    mpfr_init2 (m, 24);
    mpfr_set_flt (m, f, MPFR_RNDN);

    for (int i = 0; i < 6; i++) {
        f = nextafterf(f, 0);
        mpfr_nextbelow(m);
        cout << i << ": float: " << f << endl;
        //cout << i << ":  mpfr: " << mpfr_get_flt (m, MPFR_RNDN) << endl;
        mpfr_subnormalize (m, 1, MPFR_RNDN);
        cout << i << ":  mpfr: " << mpfr_get_flt (m, MPFR_RNDN) << endl;
    }

    mpfr_clear (m);
    return 0;
}

最佳答案

我正在复制我在ResearchGate上给出的答案(带有mpfr_subnormalize文档的链接):

有不同的约定来表示有效位数和相关的指数。 IEEE 754选择考虑1到2之间的有效位数,而MPFR(像C语言一样,请参见DBL_MAX_EXP)选择考虑1/2到1之间的有效位数(出于与多重精度有关的实际原因)。例如,数字17在IEEE 754中表示为1.0001·24,在MPFR中表示为0.10001·25。如您所见,这意味着与IEEE 754相比,MPFR中的指数增加了1,因此对于 double 而言emax = 1024而不是1023。

关于为 double 选择emin,需要能够表示2−1074 = 0.1·2-1073,因此emin最多需要为−1073(如MPFR中一样,所有数字均已归一化)。

如文档所述, mpfr_subnormalize 函数认为次正规指数范围是emin至emin + PREC(x)− 1,因此,例如,您需要设置emin = −1073以模拟IEEE double 。

10-07 20:21