Je comprends que pour comparer deux chaînes pour l'égalité, l'interprète doit parcourir les deux chaînes et comparer chaque caractère.
Cela rendrait la complexité temporelle 0(n)
où n
est la longueur de la chaîne la plus courte.
Cependant, la comparaison de deux nombres pour l'égalité est 0(1)
.
Pourquoi donc? L'interprète n'aurait-il pas à parcourir chaque numéro pour vérifier l'égalité?
Les nombres dans les ordinateurs sont généralement traités dans des unités de taille fixe. Un int
peut être de 32 ou 64 bits dans n'importe quelle combinaison de langage et/ou de compilateur/plate-forme, mais il ne sera jamais de longueur variable.
Par conséquent, vous avez un nombre fixe de bits à comparer lors de la comparaison des nombres. Il est très facile de construire un circuit matériel qui compare autant de bits à la fois (c'est-à-dire comme "une action").
Les chaînes, d'autre part, ont des longueurs intrinsèquement variables, donc vous dites simplement "chaîne" ne vous dit pas combien de bits vous devrez comparer.
Il existe des exceptions cependant, car il existe des nombres de longueur variable, généralement appelés quelque chose comme BigInteger
ou BigDecimal
qui se comporte très semblable à la comparaison String
car elle pourrait finir par être O(n) pour comparer deux BigDecimal
valeurs d'égalité (où n est la longueur de la BigDecimal
s, pas l'une de leurs valeurs numériques).
Habituellement les programmes représentent les nombres sous forme de structures de données de taille fixe (valeurs binaires, c'est pourquoi vous pouvez voir leurs tailles décrites en bits). Étant de taille fixe, les comparaisons prendraient un temps constant et seraient O (1), ce qui est l'un des avantages d'une telle représentation. Un inconvénient serait une limite sur la plage de valeurs qui peuvent être représentées.
Une représentation alternative qui lève cette restriction, permettant une gamme arbitrairement grande de nombres, ne serait donc plus de taille fixe, et ne serait plus O(1) à comparer).
Les comparaisons de chaînes sont généralement un balayage linéaire des caractères, retournant faux au premier index où les caractères ne correspondent pas.
La complexité temporelle est O(N) et le temps réel pris dépend du nombre de caractères à analyser avant que des différences n'apparaissent statistiquement. Il n'y a pas de réponse simple, mais la réponse est néanmoins évidente ;-)
si deux entiers sont égaux, il est impossible de savoir sans comparer tous leurs bits. Donc en cas d'égalité, le temps nécessaire est proportionnel au nombre de bits (qui est proportionnel à log (abs (N)) si N est l'un des comparands).
S'ils ne sont pas en fait égaux, il existe de nombreux cas, tous pertinents pour les internes d'implémentation. Les longues entrées sont stockées sous forme de vecteur de "chiffres" dans une base de puissance de 2. Si les vecteurs n'ont pas les mêmes longueurs, alors les entiers ne sont pas égaux, et cela prend un temps constant.
Mais si ce sont les mêmes longueurs, alors les "chiffres" doivent être comparés jusqu'à trouver la première paire (le cas échéant) qui ne correspond pas. Cela prend du temps proportionnel au nombre de chiffres à comparer.
En général, nous n'utilisons la notation big-O que lorsque n peut atteindre des valeurs obscènes, car la notation big-O décrit comment le temps d'exécution augmente à mesure que le l'entrée augmente. Par exemple, lors du tri d'une liste, la plupart des meilleurs algorithmes trient dans O(n log n)
- ce qui signifie, et uniquement signifie que lorsque la liste est suffisamment longue pour que le temps nécessaire pour le trier soit proportionnel à n log n
. Lorsque la liste n'est pas assez longue, d'autres facteurs (par exemple, chaque fois que votre algorithme peut prendre pour allouer de l'espace supplémentaire), deviennent importants et peuvent même prendre le temps de fonctionner.
Avec les chaînes JavaScript, n
peut en effet devenir arbitrairement grand *, donc nous disons que la comparaison prend O(n)
temps. Mais avec les nombres JavaScript (qui sont nombres à virgule flottante double précision IEEE 754 ), n
a une limite maximale de 64 - 1 pour un bit de signe, 11 pour un exposant et 53 pour les chiffres significatifs **. Pour cette raison, nous savons exactement combien de temps il faudra pour qu'une comparaison de nombres se produise, et les meilleurs systèmes que nous avons pour comparer des nombres de cette taille exacte fonctionnent plus ou moins de la même manière, quel que soit le nombre de ces 64 chiffres chaque numéro réellement a - par conséquent, la comparaison de ces nombres en JavaScript est considérée comme O(1)
.
* Techniquement, il y a une limite supérieure car RAM peut s'épuiser. Cependant, le langage ne spécifie pas de taille maximale pour les chaînes et la partie O(n)
de la comparaison de chaînes domine le temps d'exécution bien avant que cela ne se produise.
** Soit dit en passant, cela signifie que les nombres en JavaScript ne peuvent pas augmenter indéfiniment. Passé un certain point, ils commencent à jeter des chiffres plus petits (par exemple, les nombres supérieurs à 2 ^ 53 ne peuvent être que pairs, et les nombres supérieurs à 2 ^ 54 ne peuvent être divisibles que par 4), et lorsque le nombre devient assez grand, il arrondit à l'infini. Inversement, si vous divisez un nombre encore et encore pour le rendre infiniment petit, il finira par arrondir à zéro.