web-dev-qa-db-fra.com

C imprimer le premier million de nombres de Fibonacci

J'essaie d'écrire du code C qui imprimera les premiers millions de nombres de Fibonacci. 

Le problème actuel est que je veux obtenir le lats 10 chiffres de F (1 000 000)

Je comprends comment la séquence fonctionne et comment écrire le code pour y parvenir. Toutefois, étant donné que F(1,000,000) est très volumineux, je peine à trouver le moyen de la représenter.

C'est le code que j'utilise:

#include<stdio.h>

int main()
{
   unsigned long long n, first = 0, second = 1, next, c;

   printf("Enter the number of terms\n");
   scanf("%d",&n);

   printf("First %d terms of Fibonacci series are :-\n",n);

   for ( c = 0 ; c < n ; c++ )
   {
      if ( c <= 1 )
         next = c;
      else
      {
         next = first + second;
         first = second;
         second = next;
      }
      printf("%d\n",next);
   }

   return 0;
}

J'utilise long long pour essayer de m'assurer qu'il y a suffisamment de bits pour stocker le nombre.

Voici le résultat pour les premiers numéros 100:

First 100 terms of Fibonacci series are :-                                                                                                                                     

    0                                                                                                                                                                              
    1                                                                                                                                                                              
    1                                                                                                                                                                              
    2                                                                                                                                                                              
    3                                                                                                                                                                              
    5                                                                                                                                                                              
    8                                                                                                                                                                              
    13                                                                                                                                                                             
    21                                                                                                                                                                             
    34                                                                                                                                                                             
    55                                                                                                                                                                             
    89                                                                                                                                                                             
    144                                                                                                                                                                            
    233                                                                                                                                                                            
    377                                                                                                                                                                            
    610                                                                                                                                                                            
    987                                                                                                                                                                            
    1597                                                                                                                                                                           
    2584                                                                                                                                                                           
    4181                                                                                                                                                                           
    6765                                                                                                                                                                           
    10946                                                                                                                                                                          
    17711                                                                                                                                                                          
    28657                                                                                                                                                                          
    46368                                                                                                                                                                          
    75025                                                                                                                                                                          
    121393                                                                                                                                                                         
    196418                                                                                                                                                                         
    317811                                                                                                                                                                         
    514229                                                                                                                                                                         
    832040                                                                                                                                                                         
    1346269                                                                                                                                                                        
    2178309                                                                                                                                                                        
    3524578                                                                                                                                                                        
    5702887                                                                                                                                                                        
    9227465                                                                                                                                                                        
    14930352                                                                                                                                                                       
    24157817                                                                                                                                                                       
    39088169                                                                                                                                                                       
    63245986
    102334155                                                                                                                                                                      
    165580141                                                                                                                                                                      
    267914296                                                                                                                                                                      
    433494437                                                                                                                                                                      
    701408733                                                                                                                                                                      
    1134903170                                                                                                                                                                     
    1836311903                                                                                                                                                                     
    -1323752223                                                                                                                                                                    
    512559680                                                                                                                                                                      
    -811192543                                                                                                                                                                     
    -298632863                                                                                                                                                                     
    -1109825406                                                                                                                                                                    
    -1408458269
    ...

La sortie est tronquée mais vous pouvez voir le problème. Je pense que la taille du nombre généré provoque un dépassement négatif de la valeur. Je ne comprends pas comment arrêter cela en toute honnêteté.

Quelqu'un peut-il m'indiquer dans la bonne direction comment gérer réellement des nombres de cette taille?

Je n'ai pas essayé d'imprimer le premier million, car s'il échoue en imprimant F(100), il n'y a plus beaucoup d'espoir qu'il imprime F(1,000,000).

6
Chris Edwards

Vous voulez les 10 derniers chiffres de Fib (1000000). En savoir plus sur nombres de Fibonacci (et lire deux fois).

Sans trop réfléchir, vous pouvez utiliser certaines bignum librairie comme GMPlib .). Vous feriez une boucle pour calculer Fib (1000000) en utilisant une variable peumpz_t bigint (vous n'avez certainement pas besoin d'une tableau d’un million de mpz_t, mais moins de variables mpz_t que vous n’avez les doigts dans les mains). Bien sûr, vous n’imprimerez pas tous les nombres de Fibonacci, mais les derniers 1000000th un (si un ordinateur portable bon marché a aujourd’hui assez de mémoire et crache ce chiffre en moins d’une heure). Comme John Coleman a répondu , il a environ 200 000 chiffres (c’est-à-dire 2500 lignes de 80 chiffres chacune).

(En passant, si vous pensez à un programme produisant de gros résultats, vous ferez mieux d'estimer de manière approximative la taille typique de ces résultats et le temps habituel pour les obtenir; s'ils ne rentrent pas dans votre bureau ou votre ordinateur de bureau, vous avez un problème, peut-être économique: vous devez acheter plus de ressources informatiques)

Notez que l’arithmétique de bignum efficace est un sujet difficile. Il existe des algorithmes intelligents pour l'arithmétique de Bignum qui sont beaucoup plus efficaces que ceux naïfs que vous pourriez imaginer.

En fait, vous n'avez pas besoin de bigints. Lisez un manuel mathématique sur arithmétique modulaire . Le module d’une somme (ou d’un produit) correspond à la somme (ou au produit) du module. Utilisez cette propriété. Un entier de 10 chiffres tient dans un format de 64 bits int64_t donc avec certaines idées, vous n'avez pas besoin de bibliothèque Bignum.

(J'imagine qu'avec un peu plus de réflexion, vous n'avez besoin d'aucun ordinateur ni d'aucun programme C pour calculer cela. Une calculatrice bon marché, un crayon et un papier devraient suffire, et probablement, la calculatrice n'est pas du tout nécessaire.)

La leçon à apprendre lors de la programmation (ou lors de la résolution d'exercices mathématiques) est de réfléchissez au problème et essayez de reformuler la question avant de commencer à coder. J.Pitrat (un pionnier de l’Intelligence Artificielle en France, aujourd'hui retraité mais travaillant toujours sur son ordinateur) a plusieurs blog entrées connexes) intéressantes: Est-il possible de définir un problème? , Quand Donald et Gerald rencontrent Robert , etc.

Comprendre et penser au problème (et aux sous-problèmes aussi!) Est une partie intéressante du développement logiciel. Si vous travaillez au développement de logiciels, vous serez d'abord invité à résoudre des problèmes concrets (par exemple, créer un site de vente ou un aspirateur autonome) et vous devrez penser à transformer ce problème en quelque chose de codable sur un ordinateur. ordinateur. Soyez patient, vous aurez besoin de dix ans pour apprendre la programmation .

7

Pour "obtenir les 10 derniers chiffres de F (1 000 000)", appliquez simplement la fonction restante % lors du calcul de next et utilisez le spécificateur de format correct: "%llu"

Il n'est pas nécessaire de faire la somme des chiffres plus significatifs que les 10 chiffres les moins significatifs.

  // scanf("%d",&n);
  scanf("%llu",&n);
  ...
  {
     // next = first + second;
     next = (first + second) % 10000000000;
     first = second;
     second = next;
  }
  // printf("%d\n",next);
  printf("%010llu\n",next);

Ma sortie (xé les 5 derniers chiffres pour ne pas donner la réponse finale)

 66843xxxxx
5
chux

Par la formule de Binet le nième nombre de Fibonacci est approximativement le nombre d'or (environ 1,618) élevé à la puissance n puis divisé par la racine carrée de 5. Une simple utilisation des logarithmes montre que le millionième nombre de Fibonacci a donc plus de 200 000 chiffres. La longueur moyenne de l'un des premiers millions de nombres de Fibonacci est donc supérieure à 100 000 = 10 ^ 5. Vous essayez donc d’imprimer 10 ^ 11 = 100 milliards de chiffres. Je pense que vous aurez besoin de plus qu'une grande bibliothèque int pour faire cela.

D'autre part - si vous voulez simplement calculer le millionième nombre, vous pouvez le faire - bien qu'il soit préférable d'utiliser une méthode qui ne calcule pas tous les nombres intermédiaires (simplement en calculant plutôt qu'en les imprimant tous. serait toujours infaisable pour assez grand n). Il est bien connu (voir this ) que le nième nombre de Fibonacci est l’une des 4 entrées de la nième puissance de la matrice [[1,1],[1,0]]. Si vous utilisez exponentiation en quadrillant (ce qui fonctionne également pour les puissances matricielles puisque la multiplication matricielle est associative) avec une bonne bibliothèque big int - il devient parfaitement possible de calculer le millionième nombre de Fibonacci.

[On Further Edit]: Voici un programme Python permettant de calculer de très grands nombres de Fibonacci, modifié pour accepter maintenant un module optionnel. Sous le capot, il utilise une bonne bibliothèque de C bignum. 

def mmult(A,B,m = False):
    #assumes A,B are 2x2 matrices
    #m is an optional modulus
    a = A[0][0]*B[0][0] + A[0][1]*B[1][0]
    b = A[0][0]*B[0][1] + A[0][1]*B[1][1]
    c = A[1][0]*B[0][0] + A[1][1]*B[1][0]
    d = A[1][0]*B[0][1] + A[1][1]*B[1][1]
    if m:
        return [[a%m,b%m],[c%m,d%m]]
    else:
        return [[a,b],[c,d]] 

def mpow(A,n,m = False):
    #assumes A is 2x2
    if n == 0:
        return [[1,0],[0,1]]
    Elif n == 1: return [row[:] for row in A] #copy A
    else:
        d,r = divmod(n,2)
        B = mpow(A,d,m)
        B = mmult(B,B,m)
        if r > 0:
            B = mmult(B,A,m)
        return B

def Fib(n,m = False):
    Q = [[1,1],[1,0]]
    return mpow(Q,n,m)[0][1]

n = Fib(999999)
print(len(str(n)))
print(n % 10**10)
googol = 10**100
print(Fib(googol, googol))

Sortie (avec les espaces ajoutés):

208988

6684390626

3239047153240982923932796604356740872797698500591032259930505954326207529447856359183788299560546875

Notez que ce que vous appelez le millionième numéro de Fibonacci, j’appelle le 999 999e - puisqu’il est plus standard de commencer par 1 comme premier numéro de Fibonacci (et d’appeler 0 le 0 si vous voulez le compter comme un nombre de Fibonacci). Le premier numéro de sortie confirme qu'il y a plus de 200 000 chiffres et le second indique les 10 derniers chiffres (ce qui n'est plus un mystère). Le nombre final correspond aux 100 derniers chiffres du nombre googolth Fibonacci - calculé en une petite fraction de seconde. Je n'ai pas encore été capable de faire un googolplex :)

3
John Coleman

Cette question provient sans aucun doute de certains concours de programmation et vous devez les lire attentivement. 

Le millionième nombre de Fibonacci est énorme. Probablement environ 200 000 chiffres ou plus. L'impression du premier nombre de Fibonacci de 1 000 000 tuera toute une forêt d'arbres. Mais lisez attentivement: Personne ne vous demande le millionième nombre de Fibonacci. On vous demande les dix derniers chiffres de ce numéro. 

Donc, si vous avez les 10 derniers chiffres de Fib (n-2) et de Fib (n-1), comment pouvez-vous trouver les 10 derniers chiffres de Fib (n)? Comment calculer les dix derniers chiffres d'un numéro de Fibonacci sans calculer le nombre lui-même? 

PS Vous ne pouvez pas imprimer de longs nombres avec% d. Utilisez% lld. 

3
gnasher729

Votre algorithme est en fait correct. Puisque vous utilisez unsigned long long, vous avez suffisamment de chiffres pour capturer les 10 derniers chiffres et la nature des fonctions de dépassement de capacité non signées en tant qu’arithmétique modulo. Vous obtiendrez ainsi le résultat correct pour au moins les 10 derniers chiffres.

Le problème réside dans le spécificateur de format que vous utilisez pour la sortie:

printf("%d\n",next);

Le spécificateur de format %d attend un intname__, mais vous transmettez un unsigned long long. L'utilisation d'un spécificateur de format incorrect appelle un comportement non défini

Dans ce cas particulier, il est fort probable que printfrécupère les 4 octets de poids faible de next(car votre système semble être peu étendu) et les interprète comme un intsigné. Cela finit par afficher les valeurs correctes pour à peu près les 60 premiers chiffres, mais des valeurs incorrectes par la suite.

Utilisez le spécificateur de format correct et vous obtiendrez les résultats corrects:

printf("%llu\n",next);

Vous devez également faire la même chose lorsque vous lisez/imprimez nname__:

scanf("%llu",&n);

printf("First %llu terms of Fibonacci series are :-\n",n);

Voici la sortie des nombres 45 à 60:

701408733
1134903170
1836311903
2971215073
4807526976
7778742049
12586269025
20365011074
32951280099
53316291173
86267571272
139583862445
225851433717
365435296162
591286729879
956722026041
1
dbush