web-dev-qa-db-fra.com

Pourquoi la constante est-elle toujours éliminée de l'analyse des gros O?

J'essaie de comprendre un aspect particulier de l'analyse de Big O dans le contexte de l'exécution de programmes sur un PC.

Supposons que j'ai un algorithme qui a une performance de O (n + 2). Ici, si n devient vraiment grand, le 2 devient insignifiant. Dans ce cas, il est parfaitement clair que la performance réelle est O (n).

Cependant, disons qu'un autre algorithme a une performance moyenne de O (n ^ 2/2). Le livre où j'ai vu cet exemple indique que la performance réelle est O (n ^ 2). Je ne suis pas sûr de comprendre pourquoi, je veux dire le 2 dans ce cas ne semble pas complètement insignifiant. Je cherchais donc une explication claire et agréable du livre. Le livre l'explique de cette façon:

"Considérez bien ce que signifie 1/2. Le temps réel pour vérifier chaque valeur Dépend fortement de l’instruction machine à laquelle le code Correspond, puis de la vitesse à laquelle la CPU peut exécuter les instructions. le 1/2 ne veut pas dire grand chose. "

Et ma réaction est… hein ???. Je n'ai littéralement aucune idée de ce que cela dit ou plus précisément de ce que cette déclaration a à voir avec leur conclusion. Quelqu'un peut-il m'écrire, s'il vous plaît? 

Merci pour toute aide.

29
driftwood

Il y a une distinction entre "ces constantes sont-elles significatives ou pertinentes?" et "est-ce que la notation big-O se soucie d'eux?" La réponse à cette deuxième question est "non", alors que la réponse à cette première question est "absolument!"

La notation Big-O ne se soucie pas des constantes car la notation Big-O ne décrit que le taux de croissance à long terme des fonctions, plutôt que leur grandeur absolue. Multiplier une fonction par une constante n'a d'influence que constante sur son taux de croissance. Ainsi, les fonctions linéaires continuent de croître linéairement, les fonctions logarithmiques croissent toujours de manière logarithmique, les fonctions exponentielles continuent de croître de manière exponentielle, etc. Peu importe que nous abandonnions les constantes.

Cela dit, ces constantes sont absolument significatives! Une fonction dont le temps d'exécution est 10100n sera chemin plus lent qu'une fonction dont le temps d’exécution est juste n. Une fonction dont le runtime est n2 / 2 sera plus rapide qu'une fonction dont le runtime est juste n2. Le fait que les deux premières fonctions sont à la fois O(n) et les deux autres sont O (n2) ne change pas le fait qu’elles ne fonctionnent pas dans le même laps de temps, car ce n’est pas le but de la notation big-O. La notation O est utile pour déterminer si à long terme une fonction sera plus grande qu'une autre. Même si 10100n est une valeur colossalement énorme pour tout n> 0, cette fonction est O(n) et donc pour un assez grand n, elle finira par battre la fonction dont le temps d'exécution est n2 / 2 car cette fonction est O (n2).

En résumé - puisque Big-O ne parle que de classes relatives de taux de croissance, il ignore le facteur constant. Cependant, ces constantes sont absolument significatives; ils ne sont tout simplement pas pertinents pour une analyse asymptotique.

J'espère que cela t'aides!

63
templatetypedef

La notation Big-O décrit uniquement le taux de croissance des algorithmes en termes de fonction mathématique, plutôt que le temps d'exécution réel des algorithmes sur une machine.

Mathématiquement, Soit f(x) et g(x) un positif pour x suffisamment grand . Nous disons que f(x) et g(x) croître au même rythme que x tend vers l'infini, si

enter image description here

soit maintenant f (x) = x ^ 2 et g (x) = x ^ 2/2, puis lim (x-> infini) f (x)/g (x) = 2. donc x ^ 2 et x ^ 2/2 ont tous les deux le même taux de croissance. On peut donc dire O (x ^ 2/2) = O (x ^ 2).

Comme le dit templatetypedef, les constantes cachées dans les notations asymptotiques sont absolument significatives. Par exemple: le tri des marges s'exécute dans O(nlogn) dans le cas le plus défavorable et le tri par insertion dans les cas dans le pire des cas O. (Mais) les facteurs constants cachés dans le tri par insertion sont plus petits que ceux du tri par marge, en pratique, le tri par insertion peut être plus rapide que le tri par marge pour les problèmes de petite taille sur de nombreuses machines.

4
tanmoy

Vous avez tout à fait raison de dire que les constantes comptent. En comparant plusieurs algorithmes différents pour le même problème, les nombres O sans constantes vous donnent un aperçu de la façon dont ils se comparent. Si vous avez ensuite deux algorithmes dans la même classe O, comparez-les à l'aide des constantes impliquées.

Mais même pour différentes classes O, les constantes sont importantes. Par exemple, pour la multiplication à plusieurs chiffres ou grands nombres, l'algorithme naïf est O (n ^ 2), Karatsuba est O (n ^ log_2 (3)), Toom-Cook O (n ^ log_3 (5)) et Schönhage-Strassen O (n * log (n) * log (log (n))). Cependant, chacun des algorithmes les plus rapides a une surcharge de plus en plus importante, reflétée par de grandes constantes. Donc, pour obtenir des points de croisement approximatifs, il faut des estimations valides de ces constantes. Ainsi, on obtient, comme Swag, que jusqu’à n = 16, la multiplication naïve est la plus rapide, jusqu’à n = 50 Karatsuba et que le passage de Toom-Cook à Schönhage-Strassen se déroule pour n = 200.

En réalité, les points de croisement dépendent non seulement des constantes, mais également de la mise en cache du processeur et d'autres problèmes liés au matériel.

3
LutzL

Big O sans constante est suffisant pour l'analyse algorithmique.

Premièrement, le temps réel ne dépend pas seulement du nombre d'instructions mais aussi du temps de chaque instruction, qui est étroitement lié à la plate-forme où le code est exécuté. C'est plus qu'une analyse théorique. Donc, la constante n'est pas nécessaire dans la plupart des cas.

Deuxièmement, Big O sert principalement à mesurer l'augmentation du temps d'exécution à mesure que le problème s'aggrave ou la diminution de son exécution à mesure de l'amélioration des performances du matériel.

Troisièmement, pour les situations d’optimisation de hautes performances, une constante sera également prise en compte.

1
konjac

Le temps requis pour effectuer une tâche particulière sur des ordinateurs ne prend désormais plus beaucoup de jours, sauf si la valeur entrée est très grande.

Supposons que nous voulions multiplier 2 matrices de taille 10 * 10, nous n'aurons pas de problème à moins que nous voulions faire cette opération plusieurs fois, puis le rôle de les notations asymptotiques devient prépondérant et lorsque La valeur de n devient très grande alors les constantes ne font pas vraiment de différence dans la réponse et sont presque négligeables. Nous avons donc tendance à les laisser pendant le calcul de la complexité.

0
cammando

La notation Big O est le plus souvent utilisée pour décrire le temps d'exécution d'un algorithme. Dans ce contexte, je dirais que des valeurs constantes spécifiques sont essentiellement sans signification. Imaginez la conversation suivante:

Alice: Quelle est la durée d'exécution de votre algorithme?

Bob: 7n2

Alice: Qu'entendez-vous par 7n2?

  • Quelles sont les unités? Microsecondes? Millisecondes? Nanosecondes?
  • Sur quel processeur l'exécutez-vous? Intel i9-9900K? Qualcomm Snapdragon 845? (Ou utilisez-vous un GPU, un FPGA ou un autre matériel?)
  • Quel type de RAM utilisez-vous?
  • Dans quel langage de programmation avez-vous implémenté l'algorithme? Quel est le code source?
  • Quel compilateur/VM utilisez-vous? Quels indicateurs passez-vous au compilateur/VM?
  • Quel est le système d'exploitation?
  • etc.

Comme vous pouvez le constater, toute tentative d'indication d'une valeur constante spécifique est intrinsèquement problématique. Mais une fois que nous mettons de côté les facteurs constants, nous sommes en mesure de décrire clairement le temps d'exécution d'un algorithme. La notation Big O nous donne une description robuste et utile du temps que prend un algorithme, tout en faisant abstraction des caractéristiques techniques de son implémentation et de son exécution.

Il est maintenant possible de spécifier le facteur constant lors de la description du nombre d'opérations (définies de manière appropriée) ou d'instructions de la CPU exécutées par un algorithme, du nombre de comparaisons effectuées par un algorithme de tri, etc. Mais généralement, ce qui nous intéresse vraiment, c’est le temps de course.

Rien de tout cela n'est censé suggérer que les caractéristiques de performance d'un algorithme dans le monde réel sont sans importance. Par exemple, si vous avez besoin d'un algorithme pour la multiplication matricielle, l'algorithme Coppersmith-Winograd est déconseillé. Il est vrai que cet algorithme prend O (n2,376), alors que l’algorithme de Strassen, son concurrent le plus puissant, prend O (n2,808) temps. Cependant, selon Wikipedia, Coppersmith-Winograd est lent dans la pratique et "cela ne constitue un avantage que pour les matrices si grandes qu'elles ne peuvent pas être traitées par du matériel moderne". Cela s’explique généralement par le fait que le facteur constant pour Coppersmith-Winograd est très important. Mais pour répéter, si nous parlons de la durée de fonctionnement de Coppersmith-Winograd, il n’a pas de sens de donner un nombre spécifique pour le facteur constant.

Malgré ses limites, la grande notation en O est une assez bonne mesure du temps d'exécution. Et dans de nombreux cas, il nous indique quels algorithmes sont les plus rapides pour des tailles d’entrée suffisamment grandes, avant même d’écrire une seule ligne de code.

0
btrekkie