Warum werden die Zeichenfolgen 0 (n) verglichen, aber die Zahlen 0 (1)?

8

Ich verstehe, dass der Interpreter, um zwei Zeichenfolgen auf Gleichheit zu vergleichen, beide Zeichenfolgen durchlaufen und jedes Zeichen vergleichen muss.

Das würde die Zeit komplex machen, 0(n)wo ndie Länge der kürzesten Zeichenfolge ist.

Der Vergleich zweier Zahlen auf Gleichheit ist jedoch 0(1).

Warum ist das so? Müsste der Dolmetscher nicht jede Zahl durchlaufen, um die Gleichheit zu überprüfen?

Nick Akey
quelle
1
Was gibt es, um eine Zahl zu iterieren? Eine Zahl ist nur der Wert: 2zum Beispiel nicht 3. Das ist es. Ähnlich 123ist es nicht 124. Eine Zeichenfolge ist eine Sammlung von Zeichen, die "abc"sich von unterscheidet, "abd"aber Sie müssen jedes Zeichen überprüfen.
VLAZ
2
Computer verfügen über intrinsische Operationen, mit denen ganze Zahlenwerte schnell verglichen werden können.
Pointy
5
Wenn Sie in einer Sprache wie Erlang mit Ganzzahlen mit unendlicher Genauigkeit arbeiten, sind numerische Vergleiche tatsächlich O (n)
Pointy
1
Auch anstatt "durch jede Zahl" meinen Sie wahrscheinlich "durch jede Ziffer"
Pointy
1
@Pointy: Das wäre O (log (n)), da die Länge der n-Zahl proportional zu log (n) ist.
Nyos

Antworten:

10

Zahlen in Computern werden normalerweise in Einheiten fester Größe behandelt. A intkann in einer bestimmten Sprache und / oder Compiler / Plattform-Kombination 32 oder 64 Bit groß sein, hat jedoch niemals eine variable Länge.

Daher müssen Sie beim Vergleichen von Zahlen eine feste Anzahl von Bits vergleichen. Es ist sehr einfach, eine Hardwareschaltung zu erstellen, die so viele Bits gleichzeitig vergleicht (dh als "eine Aktion").

Strings hingegen haben von Natur aus variable Längen. Wenn Sie also nur "string" sagen, wissen Sie nicht, wie viele Bits Sie vergleichen müssen.

Es gibt jedoch Ausnahmen, da es Zahlen variabler Länge gibt, die normalerweise als so etwas bezeichnet werden BigIntegeroder BigDecimalsich dem StringVergleich sehr ähnlich verhalten, da es möglicherweise O (n) ist, um zwei BigDecimalWerte für die Gleichheit zu vergleichen (wobei n die Länge des BigDecimals ist , keiner ihrer numerischen Werte).

Joachim Sauer
quelle
Hat das Vorhandensein des Javascript-Tags einen Einfluss auf diese Antwort? In Javascript haben sie die Operatoren ===und ==, wobei der ==Operator zulässt, dass etwas Ähnliches 1 == '1'als wahr ausgewertet wird, aber die Dokumente sind sehr vage, in was jeder der Operanden konvertiert wird, bevor der Vergleich durchgeführt wird. Wenn sie also in einen String konvertiert werden, führt der Vergleich möglicherweise keinen Ganzzahlvergleich durch, sondern einen Stringvergleich
smac89
@ smac89: JavaScript verwendet einen einzelnen numerischen Typ, bei dem es sich um eine Gleitkommazahl fester Größe handelt, sodass es für den Vergleich keinen Unterschied macht. Ja, vor dem Vergleich müssen Sie möglicherweise einige Konvertierungen durchführen, die in O (n) möglicherweise nicht möglich sind, aber IMO ist nicht wirklich Teil des Vergleichs.
Joachim Sauer
3
@ smac89 " aber die Dokumente sind sehr vage, in was die einzelnen Operanden konvertiert werden, bevor der Vergleich durchgeführt wird ". Die Dokumente sind SEHR explizit darin, wie der Vergleich zwischen verschiedenen Typen durchgeführt werden soll.
VLAZ
@VLAZ danke für den Link. Es sieht also so aus, als würde eine Zeichenfolge in eine Zahl umgewandelt, was immer noch O(n)der Fall ist, und das ist mein Punkt, wenn ich dies besonders dann anspreche, wenn es sich um Javascript handelt.
smac89
@ JoachimSauer JavaScript uses a single numberic typedas stimmt nicht. BigInt ist jetzt ein in JavaScript
integrierter
4

Normalerweise stellen Programme Zahlen als Datenstrukturen fester Größe dar (Binärwerte, weshalb ihre Größen möglicherweise in Bits beschrieben werden). Vergleiche mit fester Größe würden eine konstante Zeit in Anspruch nehmen und O (1) sein, was einer der Vorteile einer solchen Darstellung ist. Ein Nachteil wäre eine Begrenzung des Wertebereichs, der dargestellt werden kann.

Eine alternative Darstellung, die diese Einschränkung aufhebt und einen beliebig großen Zahlenbereich zulässt, wäre daher nicht mehr in der Größe festgelegt und nicht mehr O (1) zum Vergleichen.

Scott Hunter
quelle
0

String

Zeichenfolgenvergleiche sind normalerweise ein linearer Scan der Zeichen, wobei beim ersten Index, bei dem die Zeichen nicht übereinstimmen, false zurückgegeben wird.

Die zeitliche Komplexität beträgt O (N) und die tatsächlich benötigte Zeit hängt davon ab, wie viele Zeichen gescannt werden müssen, bevor statistisch Unterschiede auftreten. Es gibt keine einfache Antwort, aber die Antwort ist trotzdem offensichtlich ;-)

Zahlen

Wenn zwei ganze Zahlen gleich sind, ist es unmöglich zu wissen, ohne alle ihre Bits zu vergleichen. Im Falle der Gleichheit ist die benötigte Zeit proportional zur Anzahl der Bits (die proportional zu log (abs (N)) ist, wenn N einer der Vergleicher ist).

Wenn sie tatsächlich nicht gleich sind, gibt es viele Fälle, die alle für Implementierungsinternale relevant sind. Lange Ints werden als Vektor von "Ziffern" in einer Zweierpotenzbasis gespeichert. Wenn die Vektoren nicht die gleichen Längen haben, sind die Ints nicht gleich, und das dauert konstant.

Wenn sie jedoch gleich lang sind, müssen die "Ziffern" verglichen werden, bis das erste (falls vorhanden) nicht übereinstimmende Paar gefunden wird. Das braucht Zeit proportional zur Anzahl der zu vergleichenden Stellen.

Mazhar Khan
quelle
Ziffern werden nicht verglichen. Bits werden verglichen. Und die Bits werden als Atomgruppe verglichen. Kein Computer vergleicht Bit 1, dann Bit 2, dann Bit 3, dann Bit 4. Abhängig von dem bestimmten verwendeten Befehl und den Fähigkeiten des Prozessors vergleichen sie 8 Bit oder 16 Bit oder 32 Bit oder 64 Bit usw. als einzelne Operation. Es gibt keinen Vergleich auf Ziffernebene oder das Äquivalent, es befindet sich an Byte- / Wortgrenzen.
Ghedipunk
0

Im Allgemeinen verwenden wir die Big-O-Notation nur, wenn n zu übermäßig großen Werten ansteigen kann, da die Big-O-Notation beschreibt, wie die Ausführungszeit mit zunehmender Eingabe zunimmt. Wenn Sie beispielsweise eine Liste sortieren, werden die meisten der besten Algorithmen sortiert. Dies O(n log n)bedeutet und bedeutet nur , dass die Zeit, die zum Sortieren der Liste benötigt wird, proportional ist, wenn die Liste lang genug ist n log n. Wenn die Liste nicht lang genug ist, werden andere Faktoren (z. B. die Zeit, die Ihr Algorithmus benötigt, um zusätzlichen Speicherplatz zuzuweisen) von Bedeutung und können möglicherweise sogar die Laufzeit übernehmen.

Mit JavaScript-Zeichenfolgen nkann in der Tat beliebig groß werden *, daher sagen wir, dass der Vergleich O(n)Zeit braucht . Bei JavaScript-Zahlen ( Gleitkommazahlen mit doppelter Genauigkeit nach IEEE 754 ) nbeträgt die maximale Obergrenze 64 - 1 für ein Vorzeichenbit, 11 für einen Exponenten und 53 für signifikante Ziffern **. Aus diesem Grund wissen wir genau, wie lange es möglicherweise dauern wird, bis ein Zahlenvergleich durchgeführt wird, und die besten Systeme zum Vergleichen von Zahlen dieser exakten Größe laufen mehr oder weniger gleich, unabhängig davon, wie viele dieser 64 Stellen tatsächlich jede Zahl tatsächlich sind hat - daher wird ein Vergleich dieser Zahlen in JavaScript in Betracht gezogen O(1).


* Technisch gesehen gibt es eine Obergrenze, da der Arbeitsspeicher knapp werden kann. Die Sprache gibt jedoch keine maximale Größe für Zeichenfolgen an, und der O(n)Teil des Zeichenfolgenvergleichs dominiert die Ausführungszeit, lange bevor dies geschieht.

** Dies bedeutet übrigens, dass die Zahlen in JavaScript nicht unendlich steigen können. Ab einem bestimmten Punkt werfen sie kleinere Ziffern weg (zum Beispiel können Zahlen über 2 ^ 53 nur gerade sein und Zahlen über 2 ^ 54 können nur durch 4 teilbar sein), und wenn die Zahl groß genug wird, wird sie aufgerundet zur Unendlichkeit. Wenn Sie dagegen eine Zahl immer wieder teilen, um sie unendlich klein zu machen, wird sie schließlich auf Null abgerundet.

Der Hansinator
quelle