0

我正在尝试获取gmp变量的机器精度。

为此,我改编了来自wikipedia的代码,以计算具有固定精度的 gmp 的精度:

int main( int argc, char **argv )
{
    long int precision = 100;

mpf_set_default_prec(precision); // in principle redundant, but who cares

    mpf_t machEps, one, temp; // "one" is the "1" in gmp. tmp is to comparison.
    mpf_init2(machEps, precision); 
    mpf_set_ui(machEps, 1); // eps = 1
    mpf_init_set(one,machEps); // ensure "one" has the same precision as machEps
    mpf_init_set(temp,machEps); // ensure "temp" has the same precision as machEps

    do {
        mpf_div_ui(machEps,machEps,2); // eps = eps/2
        mpf_div_ui(temp,machEps,2);    // temp = eps/2
        mpf_add(temp,temp,one);        // temp += 1
    }
    while ( mpf_cmp(temp,one)); // temp == 1
    /// print the result...
    char *t = new char[400];
    mp_exp_t expprt;
    mpf_get_str(NULL, &expprt, 10, 10, machEps);

    sprintf(t, "%se%ld", mpf_get_str(NULL, &expprt, 10, mpf_get_default_prec(), machEps), expprt);

    printf( "Calculated Machine epsilon: %s\n", t);
    return 0;
}

但是,结果与维基百科的公式不一致,也不会随着我设置的精度而变化。我错过了什么?我也尝试过使用 double 和 float (c 标准),结果是正确的......

4

1 回答 1

3

我得到的结果与维基百科的公式一致,并且值取决于精度。

但是,值和有效精度仅在越过肢体边界(1)时发生变化。对我来说,这意味着 64 的倍数,所以对于

(k-1)*64 < precision <= k*64

计算出的机器 epsilon 是

0.5^(k*64)

一些结果:

$ ./a.out 192
Calculated Machine epsilon: 15930919111324522770288803977677118055911045551926187860739e-57
$ ./a.out 193
Calculated Machine epsilon: 8636168555094444625386351862800399571116000364436281385023703470168591803162427e-77

为了比较:

Prelude> 0.5^192
1.5930919111324523e-58
Prelude> 0.5^256
8.636168555094445e-78

GMP 程序的输出形式mantissa,'e',exponent

0.mantissa * 10^exponent

(1) GMP 将浮点数表示为一对指数(以 2 为底)和尾数(和符号)。尾数被维护为一个无符号整数数组,即肢体。对我来说,肢体是 64 位,在 32 位系统上通常是 32 位 (iirc)。因此,当所需精度在(k-1)*LIMB_BITS(不含)和k*LIMB_BITS(含)之间时,尾数的数组包含k肢体,并且全部使用,因此有效精度为k*LIMB_BITS位。因此,epsilon 仅在肢体数量发生变化时才会发生变化。

于 2012-06-12T11:57:10.197 回答