任意浮点精度数到字符串

arbitrary floating precision number to string

我是 c 编程语言的新手。 我想要做的是以任意精度获取存储 pi 并将其转换为字符串。

int calculatePIConst (int preciznost)
{
    //init var
    mpfr_t x;
    mpfr_init2 (x, preciznost);
    //populate pi
    mpfr_const_pi (x, MPFR_RNDN);
    //turn to string
    char abc[preciznost];
    int i;
    //error RUN FINISHED; Segmentation fault; core dumped; real time: 90ms; user: 0ms; system: 0ms
    //  mpfr_get_str (abc, i, 50, 50, x, MPFR_RNDN);
    //write pi
    mpfr_printf ("PI = %1.1024RNf\n", x);
    mpfr_clear (x);
    return *abc;
}

这里是mpfr lib文档文档http://www.mpfr.org/mpfr-current/mpfr.html#Miscellaneous-Functions

来自您链接到的文档:

If str is not a null pointer, it should point to a block of storage large enough for the significand, i.e., at least max(n + 2, 7). The extra two bytes are for a possible minus sign, and for the terminating null character, and the value 7 accounts for -@Inf@ plus the terminating null character.

此外,我假设您希望结果以 10 为基数,而不是以 50 为基数。

试试这个:

char abc[preciznost + 2]; /* assuming preciznost >= 5 */
  :
mpfr_get_str (abc, i, 10, 50, x, MPFR_RNDN);

您要为 preciznost 传递什么值?我看到调用可以处理非常大的位精度,并且存在声明

破坏堆栈的危险
char abc[preciznost];

我建议您改为在堆上分配内存,记住稍后 free() 它。

char *abc = malloc(preciznost);

尽管不清楚您将使用此数组做什么。如果它是 '0''1' 位值的字符数组,则 nul 终止符需要一个额外的字节,因此

char *abc = malloc(preciznost+1);

最简单的方法是让 MPFR 分配字符串:

char* abc = NULL;
abc = mpfr_get_str (NULL, i, 10, 50, x, MPFR_RNDN);

printf ("PI = %s\n", abc);

mpfr_clear(x);
mpfr_free_str(abc);

还检查来自 C++ wrapper for the MPFR 的成员函数,例如:

inline std::string mpreal::toString(const std::string& format) const
{
    char *s = NULL;
    std::string out;

    if( !format.empty() )
    {
        if(!(mpfr_asprintf(&s, format.c_str(), mpfr_srcptr()) < 0))
        {
            out = std::string(s);

            mpfr_free_str(s);
        }
    }
    return out;
}

关键是要使用 mpfr_asprintf,它会自动分配和 returns 字符串(与 mpfr_get_str 相同),但也允许您使用格式规范。

原型为:

char *mpfr_get_str (char *str, mpfr_exp_t *expptr, int b, size_t n, mpfr_t op, mpfr_rnd_t rnd)

你的代码有两处错误:

  1. 数组不够大。参见 。但是,如果您选择使用等于 0 的 n,则最好让 MPFR 分配字符串(在所有情况下 Pavel Holoborodko 也建议)。

  2. 第二个参数必须是指向mpfr_exp_t的指针。例如: mpfr_exp_t e; mpfr_get_str (abc, &e, 10, 50, x, MPFR_RNDN);

根据 Pavel 的回答,我创建了这个函数来输出字符串。

string Autozoom::mpfrToString(const mpfr_t& in) {
    int decimalLocation;
    char* outChar = NULL;

    mpfr_exp_t mpfrDecimalLocation;
    outChar = mpfr_get_str(NULL, &mpfrDecimalLocation, 10, 0, in, MPFR_RNDN);

    decimalLocation = mpfrDecimalLocation;

    string out(outChar);

    if (out[0] == '-') {
        out.insert(decimalLocation + 1, ".");
    }
    else {
        out.insert(decimalLocation, ".");
    }

    return out;
}

这实际上会将小数点的数字插入到字符串中,然后 return。