Bailey-Borwein-Plouffe公式的麻烦

时间:2015-04-25 17:59:56

标签: c math gmp pi

我正在尝试实施BBP公式。我根据Paul H. Bailey的论文(我发现here)编写了以下快速而肮脏的测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gmp.h>
#include <limits.h>

long bin_exp_mod_k(int base, int exponent, int div) {
    long expmod = 1;
    long t;

    t = (long) pow(2, floor(log(exponent)/log(2.0)));

    while(42) {
        if(exponent >= t) {
            expmod = (base * expmod) % div;
            exponent -= t;
        }

        t = t/2;

        if(t >= 1) {
            expmod = ((long)pow(expmod, 2)) % div;
        } else
            break;
    }

    return expmod;
}

void bbp_part(mpf_t rop, int base, int index, int digit_index, int num_iter) {
    const int knum = num_iter;
    int k;
    long ldiv;
    mpf_t fbase;
    mpf_t fst_sum;
    mpf_t fst_sum_int;
    mpf_t snd_sum;
    mpf_t powval;
    mpf_t div;

    mpf_init(fst_sum);
    mpf_init(snd_sum);
    mpf_init(fst_sum_int);
    mpf_init(powval);
    mpf_init(div);
    mpf_init(rop);
    mpf_init_set_si(fbase, base);

    for(k = 0;k <= digit_index;k++) {
        ldiv = 8 * k + index;
        mpf_set_si(powval, bin_exp_mod_k(base, digit_index - k, ldiv));
        mpf_set_si(div, ldiv);
        mpf_div(powval, powval, div);
        mpf_add(fst_sum, fst_sum, powval);
    }

    mpf_trunc(fst_sum_int, fst_sum);
    mpf_sub(fst_sum, fst_sum, fst_sum_int);

    for(k = digit_index + 1;k < knum;k++) {
        ldiv = 8 * k + index;
        mpf_set_si(div, ldiv);
        mpf_pow_ui(powval, fbase, digit_index - k);
        mpf_div(powval, powval, div);
        mpf_add(snd_sum, snd_sum, powval);
    }

    mpf_set(rop, fst_sum);
    mpf_add(fst_sum, fst_sum, snd_sum);

    printf("S%i: %.20lf\n", index, mpf_get_d(rop));

    mpf_clear(fst_sum);
    mpf_clear(snd_sum);
    mpf_clear(fbase);
    mpf_clear(fst_sum_int);
    mpf_clear(powval);
    mpf_clear(div);
}

int main(int argc, char **argv) {
    const int base = 16;
    int d;
    int num_iter;
    mpf_t pi_digits;
    mpf_t part1;
    mpf_t part1_int;
    mpf_t part4;
    mpf_t part4_int;
    mpf_t part5;
    mpf_t part5_int;
    mpf_t part6;
    mpf_t part6_int;

    if(argc == 1) {
        return -1;
    }

    d = atoi(argv[1]);

    if(argc == 3) {
        num_iter = atoi(argv[2]);
    } else {
        num_iter = INT_MAX;
    }

    mpf_set_default_prec(128);

    mpf_init(pi_digits);

    mpf_init(part1_int);       
    mpf_init(part4_int);
    mpf_init(part5_int);
    mpf_init(part6_int);

    bbp_part(part1, base, 1, d, num_iter);
    bbp_part(part4, base, 4, d, num_iter);
    bbp_part(part5, base, 5, d, num_iter);
    bbp_part(part6, base, 6, d, num_iter);

    mpf_trunc(part1_int, part1);
    mpf_trunc(part4_int, part4);
    mpf_trunc(part5_int, part5);
    mpf_trunc(part6_int, part6);

    mpf_sub(part1, part1, part1_int);
    mpf_sub(part4, part4, part4_int);
    mpf_sub(part5, part5, part5_int);
    mpf_sub(part6, part6, part6_int);

    mpf_mul_ui(part1, part1, 4L);
    mpf_mul_ui(part4, part4, 2L);

    mpf_set(pi_digits, part1);
    mpf_sub(pi_digits, pi_digits, part4);
    mpf_sub(pi_digits, pi_digits, part5);
    mpf_sub(pi_digits, pi_digits, part6);

    mpf_clear(pi_digits);
    mpf_clear(part1);
    mpf_clear(part4);
    mpf_clear(part5);
    mpf_clear(part6);
    mpf_clear(part1_int);
    mpf_clear(part4_int);
    mpf_clear(part5_int);
    mpf_clear(part6_int);

    return 0;
}

它似乎是正确的,因为根据他的论文,我得到的S1,S4,S5和S6的部分结果与精确度差异很小,与之相同。

然而,我无法弄清楚我错过了什么&#34;结合了结果&#34;部分。无论我做什么,我都会0.57...而不是纸上写的0.42...

有人能看到我在这里失踪了吗?

0 个答案:

没有答案