web-dev-qa-db-ja.com

Cでbigintを実装する最も簡単な方法は何ですか?

100を計算しようとしています!

Cを使用してこれを実現する最も簡単な方法を探しています。読んだことがありますが、具体的な答えは見つかりませんでした。

知っておく必要がある場合は、Mac osXのXcodeでプログラムします。

ありがとう!

19
AlexBrand

単純なライブラリーを探しているなら、libtommath(libtomcryptから)がおそらくあなたが望むものです。

簡単な実装を自分で作成しようとしている場合(学習演習として、またはbigint機能の非常に限られたサブセットのみが必要であり、大規模なライブラリへの依存関係や名前空間の汚染などに取り組みたくないため) 、それなら私はあなたの問題のために以下を提案するかもしれません:

nに基づいて結果のサイズを制限できるため、結果を保持するために必要なサイズのuint32_tの配列を事前に割り当てるだけです。 printの結果が必要になると思います。したがって、2の累乗ではなく、10の累乗の底(つまり、底1000000000)を使用するのが理にかなっています。配列の各要素は、0から999999999までの値を保持できます。

この数値に(通常の、大きくない)整数nを掛けるには、次のようにします。

uint32_t carry=0;
for(i=0; i<len; i++) {
    uint64_t tmp = n*(uint64_t)big[i] + carry;
    big[i] = tmp % 1000000000;
    carry = tmp / 1000000000;
}
if (carry) big[len++] = carry;

nが100(またはその他の小さい数値)より大きくなることはなく、64ビット範囲に入らないようにしたい場合(または64ビットプラットフォームを使用していてuint64_tを使用したい場合) bigint配列の場合)、乗算結果が常に型に適合するように、基数を10の累乗で小さくします。

これで、結果の印刷は次のようになります。

printf("%lu", (long)big[len-1]);
for(i=len-1; i; i--) printf("%.9lu", (long)big[i-1]);
putchar('\n');

10の累乗ではなく、2の累乗をベースとして使用する場合、乗算ははるかに高速になります。

uint32_t carry=0;
for(i=0; i<len; i++) {
    uint64_t tmp = n*(uint64_t)big[i] + carry;
    big[i] = tmp;
    carry = tmp >> 32;
}
if (carry) big[len++] = carry;

ただし、結果を10進数で印刷するのはそれほど快適ではありません... :-)もちろん、結果を16進数で表示したい場合は、簡単です。

printf("%lx", (long)big[len-1]);
for(i=len-1; i; i--) printf("%.8lx", (long)big[i-1]);
putchar('\n');

お役に立てれば!他のこと(加算、2つのbigintの乗算など)の実装は、演習として残しておきます。小学校で10進数の足し算、掛け算、割り算などを行う方法をコンピュータに教えた方法を思い出してください(ただし、代わりに基数10 ^ 9または基数2 ^ 32で)。問題ありません。

23
R..

ライブラリの実装を使用する場合、標準の実装は [〜#〜] gmp [〜#〜] のようです。

mpz_t out;
mpz_init(out);
mpz_fac_ui(out,100);
mpz_out_str(stdout,10,out);

100を計算する必要があります!ドキュメントを見ることから。

6
Scott Wales

OpenSSL bn ;を使用することもできます。すでにMacOSXにインストールされています。

2
lhf

あなたはこれを行うための最も簡単な方法を求めました。だから、ここに行きます:

#include <gmp.h>
#include <stdio.h>

int main(int argc, char** argv) {
    mpz_t mynum;
    mpz_init(mynum);
    mpz_add_ui(mynum, 100);
    int i;
    for (i = 99; i > 1; i--) {
        mpz_mul_si(mynum, mynum, (long)i);
    }
    mpz_out_str(stdout, 10, mynum);
    return 0;
}

私はこのコードをテストしました、そしてそれは正しい答えを与えます。

1
Borealid