我想模拟各种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,并且e_min设置为 -1073;远低于 -1022 的正确值。我知道将指数边界设置得太紧会导致 MPFR 中的中间计算出现溢出/下溢,但我发现准确设置e_min对于确保正确的次正规数至关重要;过高或过低会导致低于正常的 MPFR 结果(用 更新mprf_subnormalize()
)与相应的不同double
结果。
我的问题是应该如何决定将哪些值传递给mpfr_set_emax()
和(尤其是) ,以保证具有指数边界e_max和e_minmpfr_set_emin()
的浮点格式的正确次规范行为?似乎没有关于此事的任何详细文档或讨论。
衷心感谢,
詹姆士。
编辑 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;
}