13

大きな階乗を計算するために、unsigned long long integer 形式を使用しています。しかし、私のコードはある時点で失敗します。それを見てもらえますか? 実際には、指数関数のテイラー展開のより大きなコードの一部ですが、その部分はこの時点では関係ありません。提案をいただければ幸いです。

ありがとう

#include <stdio.h>
#include <math.h>
//We need to write a factorial function beforehand, since we
//have factorial in the denominators.
//Remembering that factorials are defined for integers; it is
//possible to define factorials of non-integer numbers using
//Gamma Function but we will omit that.
//We first declare the factorial function as follows:
unsigned long long factorial (int);
//Long long integer format only allows numbers in the order of 10^18 so 
//we shall use the sign bit in order to increase our range.
//Now we define it,
unsigned long long
factorial(int n)
{
//Here s is the free parameter which is increased by one in each step and
//pro is the initial product and by setting pro to be 0 we also cover the
//case of zero factorial.
    int s = 1;
    unsigned long long pro = 1;
    if (n < 0)
        printf("Factorial is not defined for a negative number \n");
    else {
    while (n >= s) { 
    printf("%d \n", s);
    pro *= s;
    s++;
    printf("%llu \n", pro);
    }
    return pro;
    }
}

int main ()
{
    int x[12] = { 1, 5, 10, 15, 20, 100, -1, -5, -10, -20, -50, -100};
//Here an array named "calc" is defined to store 
//the values of x.
unsigned long long  k = factorial(25);
printf("%llu \n", k);

//int k;
////The upper index controls the accuracy of the Taylor Series, so
////it is suitable to make it an adjustable parameter. 
//int p = 500;
//for ( k = 0; k < p; k++);

}
4

7 に答える 7

7

整数型をオーバーフローしています。unsigned long longあなたにとっては64ビットの長さである可能性があります。

  • 20!0x21c3_677c_82b4_0000合うものです。
  • 21!0x2_c507_7d36_b8c4_0000合わないものです。

任意の大きな整数を有効にするGMPなどのライブラリを調べることができます。


GMP コメントを拡張します。GMP を使用して階乗を計算するコードを次に示します。

void factorial(unsigned long long n, mpz_t result) {
    mpz_set_ui(result, 1);

    while (n > 1) {
        mpz_mul_ui(result, result, n);
        n = n-1;
    }
}

int main() {
    mpz_t fact;
    mpz_init(fact);

    factorial(100, fact);

    char *as_str = mpz_get_str(NULL, 16, fact);
    printf("%s\n", as_str);

    mpz_clear(fact);
    free(as_str);
}

これにより が計算されfactorial(100)、結果は次のようになります。

0x1b30964ec395dc24069528d54bbda40d16e966ef9a70eb21b5b2943a321cdf10391745570cca9420c6ecb3b72ed2ee8b02ea2735c61a000000000000000000000000

楽しみのために、ここに C++ バージョンがあります。コンストラクタ、デストラクタ、および演算子のオーバーロードは、これらの C++ バージョンを少しきれいに見せる傾向があります。結果は以前と同じです。

#include <gmpxx.h>
#include <iostream>

int main() {
    mpz_class fact = 1;

    for (int i=2; i<=100; ++i)
        fact *= i;

    std::cout << "0x" << fact.get_str(16) << "\n";
}
于 2013-10-07T17:03:47.917 に答える
2

factorial(25) の結果は 18,446,744,073,709,551,615 であり、これは unsigned long longデータ型範囲の範囲よりも大きい

于 2013-10-07T17:05:26.163 に答える
2

long long は非常に大きいだけなので、非常に大きな数値しか表現できません。より大きな整数の正確な表現が必要な場合は、別のもの (サードパーティのライブラリまたは自分で作成したデータ型) を使用する必要があります。正確である必要がない場合は、代わりに double を使用できます。

于 2013-10-07T17:06:16.813 に答える