MPFR

时间:2016-07-29 17:53:14

标签: c++ c floating-point mpfr multiprecision

我想模拟各种 n 位二进制浮点格式,每种格式都带有指定的 e_max e_min ,带有 p 精度。我希望这些格式能够模拟低于正常的数字,忠实于IEEE-754标准。

当然,我的搜索引导我进入MPFR库,符合IEEE-754标准并且能够使用mpfr_subnormalize()函数支持子正规。但是,我使用mpfr_set_emin()mpfr_set_emax()进行了一些混淆,以正确设置启用子正常的环境。我将使用IEEE双精度作为示例格式,因为这是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的预期值。这里, p 设置为53,正如double类型所期望的那样,但 e_max 设置为1024,而不是正确值1023,并且< em> e_min 设置为-1073;远低于-1022的正确值。我知道设置指数边界太紧会导致MPFR中间计算中的溢出/下溢,但我发现设置 e_min 对于确保正确的次正规数是至关重要的;过高或过低都会导致子标准MPFR结果(使用mprf_subnormalize()更新)与相应的double结果不同。

我的问题是如何决定将哪些值传递给mpfr_set_emax()和(特别是)mpfr_set_emin(),以保证指针边界 e_max的浮点格式的正确次正规行为 e_min ?似乎没有关于此事的任何详细文件或讨论。

非常感谢,

詹姆斯。

EDIT 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);

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

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

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

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

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

1 个答案:

答案 0 :(得分:2)

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

表达有效数字和相关指数有不同的约定。 IEEE 754选择考虑1和2之间的有效数,而MPFR(如C语言,例如参见DBL_MAX_EXP)选择考虑1/2和1之间的有效数(由于与多精度相关的实际原因)。例如,数字17在IEEE 754中表示为1.0001·2 4 ,在MPFR中表示为0.10001·2 5 。如您所见,这意味着MPFR中的指数与IEEE 754相比增加1,因此e max = 1024而不是1023(双精度)。

关于选择e min 的双精度,需要能够代表2 -1074 = 0.1·2 -1073 ,因此e min 最多需要-1073(如在MPFR中,所有数字都被标准化)。

如记载的那样,mpfr_subnormalize函数认为次正规指数范围是从e min 到e min + PREC(x) - 1,所以例如,您需要设置e min = -1073来模拟IEEE双精度。