n-ième nombre de fibonacci dans sublinéaire temps
Est-il un algorithme pour calculer le n-ième nombre de fibonacci dans la sous-linéaire dans le temps?
- On pourrait dire que c'est lié à des algorithmes, depuis l'OP fait une vague allusion à la complexité algorithmique... je serais toujours curieux de ce algorithme de bien.
- Les deux réponses ci-dessous ont la bonne formule. Si cette question est en relation avec la programmation: c'est une partie de l'informatique. L'appareil utilisé pour dériver la formule est connue comme "générer" et a un rôle important dans l'algorithme d'analyse.
- Lors de la génération de fonctions sont utiles, ils ne sont pas nécessaires pour tirer le fermé forme d'expression de la séquence de Fibonacci.
- Vous avez un problème que vous voulez résoudre, pour quelque raison que ce soit, et que vous voulez le faire de manière efficace. Parfois, la compréhension voulue sera une nouvelle mise en œuvre, parfois un algorithme, et parfois les mathématiques. Il n'est pas nécessaire pour dénoncer la situation comme "pas de programmation relative" à chaque fois que ce dernier arrive.
- La taille du résultat est linéaire en n. Il n'est donc pas un tel algorithme. Bien sûr, cela ne veut pas invalider tout de nice réponses ci-dessous qui calculer les nombres de Fibonacci à l'aide de O(log n) opérations arithmétiques.
- Oui. Parce qu'ils sont le calcul des approximations.
- Il ressemble à stackoverflow.com/questions/30595844/...
- Cela dépend de ce qui est "du temps": si le "temps" est mesuré dans des opérations arithmétiques, alors vous pouvez calculer le résultat en log(n) fois. Si le "temps" est mesurée en bits, alors vous ne pouvez pas. Notez que dans une grande partie de la théorie de la complexité, le choix de "temps" est flexible (par exemple: algorithmes de tri d'utilisation "du temps" pour désigner les comparaisons par paires, et également d'une table de hachage de l'analyse de l'utilisation "du temps" pour les comparaisons de moyennes). Ni l'un ni l'décrire avec précision le temps qu'il effectuait sur un "vrai" ordinateur (parce que le calcul d'un hash n'est pas O(1) pour arbitraire de gros objets), mais personne ne se plaint de mer).
Vous devez vous connecter pour publier un commentaire.
La
n
ème nombre de Fibonacci est donnée paroù
En supposant que la primitive d'opérations mathématiques (
+
,-
,*
et/
) sontO(1)
vous pouvez utiliser ce résultat pour calculer lan
ème nombre de Fibonacci dansO(log n)
temps (O(log n)
en raison de l'élévation à la puissance de la formule).En C#:
const
plutôt questatic
, juste pour être sûr.1 / Math.Sqrt(5)
et(1 + Math.Sqrt(5)) / 2
que C# ne pas laisserconst
valeurs calculées à l'aide deMath.Sqrt
. Pour nos besoins ici, la formule est plus clair pour comprendre que le mystérieux valeurs décimales serait.phi^n / sqrt(5) + 1/2
oùphi = (1 + sqrt(5)) / 2
. C'est un fait. Deuxièmement, je comprends le point que d'autres ont au sujet de la longueur de la réponse étantO(n)
mais j'ai ajouté une remarque à ma réponse en supposant que la primitive opérations mathématiques de prendre de la constante de temps (je sais qu'ils ne sont pas, sauf si vous avez lié les intrants). Mon point est que nous pouvons trouver le n-ième nombre de Fibonacci dansO(log n)
les opérations arithmétiques.double foo = 1.6; printf ("%.40f\n", foo);
Imprime:1.6000000000000000888178419700125232338905
Maintenant ce n'est à prévoir en raison de la norme IEEE 754 en virgule flottante. Tentez votre constantes ci-dessus:double foo = 1.6180339887498948482045868343656; printf ("%.40f\n", foo);
Imprime:1.6180339887498949025257388711906969547272
Donc, la question est de savoir quand est-ce que l'erreur d'arrondi début à la question?Math.Floor
. Le résultat de l'exécution de ce code, même sur un pathétique machine qui ne dispose pas d'une précision infinie, est lan
ème nombre de Fibonacci.a,b = b, a+b
algorithme fait la même chose. Toutefois, si vous modifiezint
àlong
dans le C#, puis il fait une erreur à n=71.La suite de Pillsy référence à des exponentielles de matrices, telles que pour la matrice
puis
Sensibilisation des matrices de pouvoirs utilisation répétée de la multiplication n'est pas très efficace.
Deux approches pour des exponentielles de matrices sont diviser et conquérir ce qui donne Mn dans S(ln n) étapes, ou de la valeur propre de décomposition qui est de la constante de temps, mais peut introduire des erreurs à cause du peu de précision en virgule flottante.
Si vous voulez l'exacte valeur supérieure à la précision de votre point flottant de mise en œuvre, vous devez utiliser l'O ( ln n ) approche basée sur cette relation:
La valeur propre de décomposition sur M trouve deux matrices U et Λ tels que Λ est diagonale et
Élever un la diagonale de la matrice de Λ de la nth puissance est une simple question d'élever chaque élément de Λ de la nth, de sorte que cela donne un O(1) méthode de collecte de M de la nth pouvoir. Cependant, les valeurs de Λ ne sont pas susceptibles d'être des entiers, de sorte que certains d'erreur va se produire.
La définition de Λ pour notre matrice 2x2 comme
De trouver chaque λ, nous résolvons
qui donne
à l'aide de la formule quadratique
Si vous avez lu la réponse de Jason, vous pouvez voir où cela va aller.
De problèmes pour les vecteurs propres X1 et X2:
Ces vecteurs donner U:
De l'inversion de U à l'aide de
donc U-1 est donnée par
Sanity check:
De sorte que la vérification générale détient.
Maintenant, nous avons tout ce dont nous avons besoin pour calculer Mn1,2:
donc
Qui est d'accord avec la formule donnée ailleurs.
Vous pouvez obtenir à partir d'une relation de récurrence, mais en ingénierie de l'informatique et de la simulation, le calcul de valeurs propres et vecteurs propres de matrices de grande taille est une activité importante, car elle donne de la stabilité et des harmoniques de systèmes d'équations, ainsi que de permettre d'élever des matrices à haute pouvoirs efficacement.
Si vous voulez le nombre exact (qui est un "bignum", plutôt qu'un int/float), je crains que
C'est impossible!
Comme indiqué ci-dessus, la formule pour les nombres de Fibonacci est:
Combien de chiffres est
fib n
?Depuis l'demandé résultat est de O(n), il ne peut pas être calculé en moins de O(n) temps.
Si vous voulez seulement la baisse des chiffres de la réponse, alors il est possible de calculer des sous-linéaire dans le temps à l'aide de la matrice de l'élévation à la puissance de la méthode.
O(n*log n)
pour la comparaison basée sur le tri d'une séquence den
nombres, où chacun aO(log n)
chiffres?L'un des les exercices de SICP est à propos de ce, qui a la réponse décrit ici.
À l'impératif de style, le programme devrait ressembler à quelque chose comme
twisted
cadre).Vous pouvez le faire par exponentiating une matrice d'entiers ainsi. Si vous avez la matrice
puis
(M^n)[1, 2]
va être égale à lan
ème nombre de Fibonacci, si[]
est une matrice indice et^
est exponentielles de matrices. Pour une taille fixe de la matrice, l'exponentiation à un positif intégrale de la puissance peut être fait en O(log n) le temps de la même manière que les nombres réels.EDIT: bien sûr, selon le type de réponse que vous voulez, vous pourriez être en mesure de s'en tirer avec une constante de temps de l'algorithme. Comme les autres formules de spectacle, le
n
ème nombre de Fibonacci croît de façon exponentielle avecn
. Même avec la version 64 bits des entiers non signés, vous aurez seulement besoin d'un 94-entrée de la table de recherche afin de couvrir l'ensemble de la gamme.DEUXIÈME EDIT: Faire de la matrice exponentielle avec un eigendecomposition première est exactement équivalente à JDunkerly la solution ci-dessous. Les valeurs propres de cette matrice sont les
(1 + sqrt(5))/2
et(1 - sqrt(5))/2
.Wikipedia a fermé solution de la forme
http://en.wikipedia.org/wiki/Fibonacci_number
Ou en c#:
|1 - phi|^n / sqrt(5) < 1/2
quandn
est un entier non négatif.Pour vraiment gros, cette fonction récursive œuvres. Il utilise les équations suivantes:
Vous avez besoin d'une bibliothèque qui vous permet de travailler avec de grands entiers. J'utilise le BigInteger bibliothèque de https://mattmccutchen.net/bigint/.
Commence par un tableau de nombres de fibonacci. Utiliser des bobards[0]=0, bobards[1]=1, bobards[2]=1, bobards[3]=2, bobards[4]=3, etc. Dans cet exemple, j'utilise un tableau de la première 501 (en partant de 0). Vous pouvez trouver les 500 premiers non nuls nombres de Fibonacci ici: http://home.hiwaay.net/~jalison/Fib500.html. Il prend un peu de retouche pour la mettre dans le bon format, mais ce n'est pas trop dur.
Ensuite, vous pouvez trouver n'importe quel nombre de Fibonacci à l'aide de cette fonction (en C):
J'ai testé cela pour les 25 000 ème nombre de Fibonacci et la comme.
Voici ma version récursive qui parcourt log(n) fois. Je pense que c'est plus facile à lire dans la forme récursive:
Cela fonctionne parce que vous pouvez calculer
fib(n),fib(n-1)
à l'aide defib(n-1),fib(n-2)
si n est impair, et si n est pair, vous pouvez calculerfib(n),fib(n-1)
à l'aide defib(n/2),fib(n/2-1)
.Le cas de base et l'étrange cas sont simples. Pour dériver le même cas, avec a,b,c consécutive de fibonacci valeurs (par exemple, 8,5,3) et de les écrire dans une matrice, avec a = b+c. Avis:
À partir de cela, nous voyons qu'une matrice des trois premiers nombres de fibonacci, fois une matrice de trois mandats consécutifs de la suite de fibonacci, est égale à la prochaine. Donc, nous savons que:
Donc:
La simplification de la droite conduit à la même affaire.
à l'aide de R
En dehors de réglage fin par des approches mathématiques, l'une des meilleures solution optimale (je crois) est à l'aide d'un dictionnaire afin d'éviter des calculs répétitifs.
Nous commençons avec trivial dictionnaire (les deux premières valeurs de la suite de Fibonacci) et l'ajout constant de Fibonacci valeurs pour le dictionnaire.
Il a fallu environ 0,7 secondes pour la première 100000 Fibonacci valeurs (Intel Xeon CPU E5-2680 @ 2.70 GHz, 16 GO de RAM, Windows 10 à 64 bits de l'OS)
voir diviser et conquérir de l'algorithme de ici
Le lien a pseudocode pour les exponentielles de matrices mentionné dans les réponses à cette question.
Point fixe de l'arithmétique est inexacte. Jason code C# donne une mauvaise réponse, pour n = 71 (308061521170130 au lieu de 308061521170129) et au-delà.
Pour la réponse correcte, utiliser un calcul d'algèbre système. Sympy est une bibliothèque pour le langage Python. Il y a une console interactive à http://live.sympy.org/ . Copier et coller cette fonction
Puis calculer
Vous pouvez essayer d'inspection
phi
.Vous pouvez utiliser le bizarre carré rooty équation pour obtenir une réponse exacte. La raison en est que le $\sqrt(5)$ tombe à la fin, vous avez juste à garder la trace des coefficients avec votre propre multiplication format.
Voici un one-liner qui calcule F(n), en utilisant des entiers de taille O(n), O(log n) opérations arithmétiques:
En utilisant des entiers de taille O(n) est raisonnable, étant donné que c'est comparable à la taille de la réponse.
Pour comprendre cela, laissez-phi être le nombre d'or (la plus grande solution de x^2=x+1) et F(n) le n-ième nombre de Fibonacci, où F(0)=0, F(1)=F(2)=1
Maintenant, phi^n = F(n-1) + F(n)phi.
Également des nombres de la forme (a+b*phi), où a, b sont des entiers sont fermés en vertu de la multiplication.
À l'aide de cette représentation, on peut calculer phi^n en O(log n) opérations sur entiers en utilisant l'exponentiation par la quadrature. Le résultat sera F(n-1)+F(n)phi, à partir de laquelle on peut lire le n-ième nombre de Fibonacci.
Noter que la majorité de ce code est un standard de l'exponentiation par la quadrature de la fonction.
Pour obtenir le one-liner qui commence cette réponse, on peut noter que représentant dmp par un assez grand nombre entier
X
, on peut effectuer(a+b*phi)(c+d*phi)
comme l'entier de l'opération(a+bX)(c+dX) modulo (X^2-X-1)
. Puis lepow
fonction peut être remplacé par le standard de Pythonpow
fonction (qui comporte un troisième argumentz
qui calcule le résultat moduloz
. LeX
choisi est2<<i
.