web-dev-qa-db-ja.com

大きな数を合計する方法は?

1 + 1 * 2 + 1 * 2 * 3 + 1 * 2 * 3 * 4 + ... + 1 * 2 * ... * nを計算しようとしています。nはユーザー入力です。 nの値が12までの場合に機能します。n = 13n = 14、およびn = 15の合計を計算します。 C89でこれを行うにはどうすればよいですか?私が知っているように、unsigned long long intはC99またはC11でのみ使用できます。

  1. 入力13、結果2455009817、期待値6749977113
  2. 入力14、結果3733955097、期待値93928268313
  3. 入力15、結果1443297817、期待値1401602636313

私のコード:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    unsigned long int n;
    unsigned long int P = 1;
    int i;
    unsigned long int sum = 0;
    scanf("%lu", &n);
    for(i = 1; i <= n; i++)
    {
        P *= i;
        sum += P;
    }
    printf("%lu", sum);
    return 0;
}
32
Timʘtei

実際には、 任意精度の算術演算 (別名bigintまたはbignum)ライブラリ。私の推奨は GMPlib ですが、 その他のもの があります。

独自のbignumライブラリをコーディングしようとしないでください。効率的で賢いアルゴリズムが存在しますが、それらは直感的ではなく、把握するのが困難です(その質問に関する本全体を見つけることができます)。さらに、GMPlibのような既存のライブラリは、標準のCコンパイラが発行しない特定のマシン命令(たとえば [〜#〜] adc [〜#〜] -add with carry)を利用しています。純粋なCコード)。

これが宿題であり、外部コードの使用が許可されていない場合は、たとえば、baseまたは radix 1000000000(10億)で数値を表すことを検討し、非常に単純な方法で操作をコーディングしますあなたが子供として学んだこと。しかし、より効率的なアルゴリズムが存在することに注意してください(そして実際のbignumライブラリがそれらを使用している)。

数値は、それぞれがベース1000000000の「数字」であるunsignedの配列を持つことにより、ベース1000000000で表すことができます。したがって、配列(おそらくmallocを使用して割り当てられるヒープ)それらの長さ。

88

特にプラットフォームでIEEE754を使用している場合は、doubleを使用できます。

このようなdoubleを使用すると、53ビットの精度が得られます。つまり、整数は53の2乗まで正確です。この場合はこれで十分です。

プラットフォームでIEEE754を使用していない場合は、採用されている浮動小数点スキームに関するドキュメントを参照してください。それmight適切である。

20
Bathsheba

MaxIntの制限を超えたときの簡単なアプローチは、適切なnに対して10 ^ nを法とする計算を行い、浮動小数点計算と同じ計算を行いますが、すべてを10 ^ rで除算することです。前者の結果は、最初のn桁を返し、後者の結果は、最初のr桁が削除された答えの最後の桁を返します。この場合、ここの最後の数桁は丸め誤差のために不正確になるため、nより少し小さいrを選択する必要があります。この場合、n = 9およびr = 5を使用するとうまくいきます。

0
Count Iblis