2011-06-06 53 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_樣式函數。