web-dev-qa-db-fra.com

Comment additionner de grands nombres?

J'essaie de calculer 1 + 1 * 2 + 1 * 2 * 3 + 1 * 2 * 3 * 4 + ... + 1 * 2 * ... * nn est l'entrée utilisateur. Cela fonctionne pour les valeurs de n jusqu'à 12. Je veux calculer la somme pour n = 13, n = 14 et n = 15. Comment faire cela en C89? Comme je sais, je peux utiliser unsigned long long int uniquement en C99 ou C11.

  1. Entrée 13, résultat 2455009817, attendu 6749977113
  2. Entrée 14, résultat 3733955097, attendu 93928268313
  3. Entrée 15, résultat 1443297817, attendu 1401602636313

Mon code:

#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

En pratique, vous voulez une arithmétique de précision arbitraire (aka bigint ou bignum) bibliothèque. Ma recommandation est GMPlib mais il y a autres .

N'essayez pas de coder votre propre bibliothèque bignum. Des algorithmes efficaces et intelligents existent, mais ils sont peu intuitifs et difficiles à saisir (vous pouvez trouver des livres entiers consacrés à cette question). De plus, les bibliothèques existantes comme GMPlib tirent parti d'instructions machine spécifiques (par exemple ADC -add with carry) qu'un compilateur C standard n'émettra pas (de code C pur).

Si c'est un devoir et que vous n'êtes pas autorisé à utiliser du code externe, pensez par exemple à représenter un nombre en base ou radix 1000000000 (un milliard) et codez-vous les opérations de manière très naïve, similaire à ce que vous avez appris enfant. Mais sachez qu'il existe des algorithmes plus efficaces (et que de vraies bibliothèques Bignum les utilisent).

Un nombre pourrait être représenté dans la base 1000000000 en ayant un tableau de unsigned, chacun étant un "chiffre" de base 1000000000. Vous devez donc gérer les tableaux (probablement tas alloué, en utilisant malloc) et leur longueur.

88

Vous pouvez utiliser un double, surtout si votre plate-forme utilise IEEE754.

Un tel double vous donne 53 bits de précision, ce qui signifie que les entiers sont exacts jusqu'à la 53e puissance de 2. C'est assez bon pour ce cas.

Si votre plateforme n'utilise pas IEEE754, consultez la documentation sur le schéma à virgule flottante adopté. Il pourrait être adéquat.

20
Bathsheba

Une approche simple lorsque vous êtes juste au-dessus de la limite de MaxInt, est de faire les calculs modulo 10 ^ n pour un n approprié et vous faites le même calcul que le calcul en virgule flottante mais où vous divisez tout par 10 ^ r. vous donnera les n premiers chiffres tandis que le dernier résultat vous donnera les derniers chiffres de la réponse avec les premiers r chiffres supprimés. Ensuite, les derniers chiffres ici seront inexacts en raison d'erreurs d'arrondi, vous devez donc choisir r un peu plus petit que n. Dans ce cas, prendre n = 9 et r = 5 fonctionnera bien.

0
Count Iblis