2011-06-06 314 views
3

有没有办法将mpz_t变量转换为unsigned long long在C中?反过来,从ull到mpz_t怎么样?gmp库不支持这个你是C99的一部分。 我发现this但它是在C++中,我不知道如何在C++中编写代码。mpz_t为无符号long long转换(gmp lib)

+0

我很惊讶没有提及mpz_import/mpz_export。 – 2013-01-31 18:20:26

+0

@MarcGlisse为了公平起见,我不是gmp专家,我只是简单地尝试将链接的C++代码直接转换为C. – 2013-08-25 02:31:47

回答

5

这里有一些功能unsigned long longmpz_t之间的转换。需要注意的是mpz2ull将粉碎你的筹码,如果数字是太大,不适合到unsigned long long

unsigned long long mpz2ull(mpz_t z) 
{ 
    unsigned long long result = 0; 
    mpz_export(&result, 0, -1, sizeof result, 0, 0, z); 
    return result; 
} 

void ull2mpz(mpz_t z, unsigned long long ull) 
{ 
    mpz_import(z, 1, -1, sizeof ull, 0, 0, &ull); 
} 
+0

非常好...谢谢。我不熟悉strtoull,为什么它的第二个参数设置为0? – kaiseroskilo 2011-06-06 07:36:19

+0

@kaiseroskilo:第二个参数需要一个“结束指针”,它(如果给出的话)被设置为数字解析的结尾。这样,您可以进行错误检查:如果结尾位于空终止符处,则整个字符串是有效数字。通过传递null(在我的代码中写为0),这就是说我不关心结束指针,因为我盲目地相信'gmp_snprintf'总是会提供有效的输出。 ;-) – 2011-06-06 07:41:28

+0

谢谢。在第二个函数上获得segfault,可能只需要mpz_t结果后的mpz_init(result); – DannyKK 2012-01-29 23:54:09

-2

Here是列出的一些转换方法。 使用这些你可以不喜欢

unsigned long long mpz_to_ull(mpz_t n) 
{ 
    double d = mpz_get_d(n); 
    if(d < (double) ULLONG_MAX) 
    return (unisgned long long) d; 
    //raise an error here: n doesn't fit in ull 
} 
+2

-1编号转换为“double”通常会导致精度损失,特别是如果数字很大。 – 2011-06-06 07:17:17

3

这些功能应该努力mpz_t之间的转换和符号/无符号很长很长。他们应该是相当快,因为​​他们避免必须做字符串处理:

void mpz_set_sll(mpz_t n, long long sll) 
{ 
    mpz_set_si(n, (int)(sll >> 32));  /* n = (int)sll >> 32 */ 
    mpz_mul_2exp(n, n, 32);    /* n <<= 32 */ 
    mpz_add_ui(n, n, (unsigned int)sll); /* n += (unsigned int)sll */ 
} 

void mpz_set_ull(mpz_t n, unsigned long long ull) 
{ 
    mpz_set_ui(n, (unsigned int)(ull >> 32)); /* n = (unsigned int)(ull >> 32) */ 
    mpz_mul_2exp(n, n, 32);     /* n <<= 32 */ 
    mpz_add_ui(n, n, (unsigned int)ull);  /* n += (unsigned int)ull */ 
} 

unsigned long long mpz_get_ull(mpz_t n) 
{ 
    unsigned int lo, hi; 
    mpz_t tmp; 

    mpz_init(tmp); 
    mpz_mod_2exp(tmp, n, 64); /* tmp = (lower 64 bits of n) */ 

    lo = mpz_get_ui(tmp);  /* lo = tmp & 0xffffffff */ 
    mpz_div_2exp(tmp, tmp, 32); /* tmp >>= 32 */ 
    hi = mpz_get_ui(tmp);  /* hi = tmp & 0xffffffff */ 

    mpz_clear(tmp); 

    return (((unsigned long long)hi) << 32) + lo; 
} 

long long mpz_get_sll(mpz_t n) 
{ 
    return (long long)mpz_get_ull(n); /* just use unsigned version */ 
} 

功能签名应该看起来像本地GMP功能。 与其他gmpz_set_函数一样,这些函数假设传递的变量已经被初始化了,但很容易将它们改为gmp_init_set_样式函数。