Ich weiß, dass dies ein bisschen ungewöhnlich klingt, in der Tat habe ich immer in der Box nachgedacht, aber in letzter Zeit habe ich darüber nachgedacht, ob die Informatik ein hohes Maß an Freiheit bietet, um andere Programme als zu entwickeln diejenigen, die an der Universität gelehrt.
Betrachten Sie die Fakultätsfunktion. Typischerweise definieren wir diese Funktion wie folgt
int fact(int n)
{
int r = 1;
for(int i=2;i<=n;i++)
r = r*i;
return r;
}
Ich würde das einen Algorithmus nennen und zweifle nicht daran, dass dies der richtige Weg ist. Dann fragte ich mich: "Kann ich das in konstanter Zeit tun?", Was zu der folgenden Idee führte: Was wäre, wenn ich ein Array von ganzen Zahlen hätte, in dem array [n] die Fakultät von n beherbergt? Sobald dieses Array gefüllt ist, kann ich einfach Folgendes definieren:
int fact(int n)
{
return array[n];
}
Ich kann es immer noch nicht als Algorithmus bezeichnen, obwohl es das richtige Ergebnis liefert und in der konstanten Zeit O (1) arbeitet. Kann man das einen Algorithmus nennen? Ansonsten warum nicht? Ich könnte argumentieren, dass das Füllen des Arrays einen Algorithmus erfordern würde, der irgendwann funktioniert, selbst wenn er sich in unserem Gehirn befindet, damit wir das Array füllen können, aber könnte dies das Kriterium sein? Wie werden diese Aspekte formal behandelt?
Beachten Sie, dass dieses Konzept auf jede Funktion erweitert werden kann, die unabhängig von der Anzahl der Argumente über ganze Zahlen operiert. Ich müsste nur eine Matrix verwenden, wenn die Funktion 2 Argumente hat, oder 3, wenn die Funktion 3 Argumente hat, und so weiter. Werden diese Lösungen nicht einfach wegen des Speicherverbrauchs verwendet?
Auch nicht, dass Funktionen auch jedes Programm mit Ausgabe umfassen könnten, da ich einen Weg finden könnte, jede einzelne mögliche Ausgabe zu indizieren, die ein Programm liefern könnte.
Betrachten Sie als weiteres Beispiel die übliche Verwendung eines Arrays: Ich ordne zunächst ein Array der Größe N zu, dann füge ich dem Array Elemente hinzu, indem ich den Wert am Index n speichere und n um eine Einheit erhöhe. Wenn ich dann nach einem Element suchen möchte, kann ich nicht anders, als eine lineare Suche über das Array durchzuführen. Wenn ich stattdessen ein Array mit einer Größe erstellt hätte, zum Beispiel Integer.MAXVALUE, um mit Nullen initialisierte Ganzzahlen zu speichern, könnte ich eine Ganzzahl speichern, indem ich 1 an ihren Index setze. Dann könnte ich in O (1) nach seiner Existenz im Array suchen. Was wäre, wenn ich in der Lage sein wollte, mehrere Einheiten derselben Nummer zu platzieren? Kein Problem, ich würde nur den Wert erhöhen, der im Ganzzahlindex gespeichert ist.
Das Sortieren wäre etwas komplizierter, aber das Nachschlagen und Hinzufügen könnte trotzdem in O (1) -Zeit erfolgen.
quelle
Antworten:
Die informelle Definition eines Algorithmus in einem populären Lehrbuch sieht ungefähr so aus:
Ein Algorithmus ist (1) eine genau definierte Rechenprozedur (2), die eine Eingabe benötigt und (3) eine Ausgabe (4) für ein genau definiertes Rechenproblem erzeugt.
In Ihrem ersten Fall haben Sie einen Algorithmus codiert, bei dem: Das Problem besteht darin, die Fakultät (Teil 4 der Definition) zu finden, wobei als Eingabe int n (Teil 2 der Definition) angegeben wird und der Code die durchzuführende Berechnung beschreibt (Teil 1 der Definition) ) ist die Ausgabe die Fakultät (Teil 3 der Definition).
In Ihrem zweiten Fall: Das Problem besteht darin, das Array-Element an Position n (Teil 4 der Definition) zu finden, wobei n als Eingabe (Teil 3 der Definition) angegeben wird. Der Code beschreibt die durchzuführende Berechnung (Teil 2 der Definition) Ausgabe ist das Element an Position n (Teil 1 der Definition).
Sie haben Fakultäten dort gespeichert, sodass Sie Fakultäten erhalten. Wenn Sie Quadrate oder Würfel dort gespeichert hätten, würden Sie Quadrate oder Würfel erhalten, sodass nicht gesagt werden kann, dass das zweite Snippet für sich genommen ein Algorithmus zur Berechnung von Fakultäten ist.
Und wenn Sie sagen, dass ein Array, das zusammen mit einem Array mit f (n) an Position n nachschlägt, ein Algorithmus zur Berechnung von f (n) ist, sind Sie so tief gegangen, dass unten keine Berechnung mehr erfolgt. Eine genau definierte Rechenprozedur sollte eine endliche Information sein. Wenn eine unendliche Anzahl von Fakultäten Teil des Rechenverfahrens ist, gilt dies nicht. Das wäre also kein Algorithmus zur Berechnung von Fakultäten.
quelle
Im Allgemeinen besteht ein Algorithmus aus einer Reihe von Schritten zur Lösung eines Problems .
In CS wird im Allgemeinen Folgendes verstanden / angenommen, wenn der Begriff Algorithmus verwendet wird:
Vor der Gründung von CS hatten Mathematiker dieselben Bedenken, die Sie geäußert haben, und formale Definitionen der Berechnung eingeführt, um diese Bedenken auszuräumen. Daher können wir heutzutage alle oben genannten Annahmen formalisieren, indem wir einfach sagen: "Ein Algorithmus ist eine Prozedur, die auf einer Turing-Maschine implementiert werden kann . " Dies ist wahrscheinlich die beste formale Antwort auf Ihre Frage.
Beachten Sie, dass die Church-Turing-These besagt, dass es unserer Meinung nach keine "leistungsfähigere" Formalisierung von Algorithmen gibt als die Turing-Maschine.
Das Fakultätsbeispiel geht auf ein anderes Berechnungsmodell über, das als ungleichmäßige Berechnung bezeichnet wird. Eine Turing-Maschine ist ein Beispiel für ein einheitliches Berechnungsmodell: Sie hat eine einzige, endliche Beschreibung und funktioniert für Eingaben beliebig großer Größe. Mit anderen Worten, es gibt ein TM, das das Problem für alle Eingabegrößen löst.
Wir könnten stattdessen die Berechnung wie folgt betrachten: Für jede Eingabegröße gibt es ein TM (oder ein anderes Rechengerät), das das Problem löst. Das ist eine ganz andere Frage. Beachten Sie, dass ein einzelnes TM nicht die Fakultät jeder einzelnen Ganzzahl speichern kann, da das TM eine endliche Beschreibung hat. Wir können jedoch ein TM (oder ein Programm in C) erstellen, das die Fakultäten aller Zahlen unter 1000 speichert. Dann können wir ein Programm erstellen, das die Fakultäten aller Zahlen zwischen 1000 und 10000 speichert. Und so weiter.
Diese ungleichmäßigen Berechnungstypen werden typischerweise in theoretischen CS durch Schaltungen modelliert. Sie berücksichtigen für jede mögliche Eingangsgröße einen anderen Schaltungsaufbau.
Uneinheitliche Rechenmodelle werden im Allgemeinen nicht als Algorithmen angesehen , auch wenn sie zu meinem ersten Satz passen. Der Grund dafür ist, dass sie nicht zu unseren Hauptannahmen passen: Sie haben keine endliche Beschreibung, die implementiert werden kann, um das "ganze" Problem für jede Eingabegröße zu lösen. Vielmehr benötigen sie eine immer umfangreichere Beschreibung, je größer das Problem wird (beispielsweise eine größere Nachschlagetabelle). Sie sind jedoch immer noch interessante Berechnungsmodelle.
quelle
Ein Algorithmus ist ein in C geschriebenes Programm, das für jede Länge von Eingaben funktionieren sollte (unter der Annahme eines unendlichen Speichers und unbegrenzter Ganzzahlen). Wenn in Ihren Beispielen das Programm für alle Eingaben funktionieren soll , ist die Tabelle, in der die Ergebnisse gespeichert werden, unendlich groß. Programme in C sind immer endlich, so dass dieser Ansatz nicht verwendet werden kann.
Die Definition des Algorithmus ist sehr widerstandsfähig: In den Anfängen der Rekursionstheorie wurden viele Definitionen vorgeschlagen, von denen gezeigt wurde, dass sie alle gleichwertig sind. Beispielsweise können Sie anstelle von C Turing-Maschinen verwenden. Diese Modelle sind jedoch in Bezug auf die Effizienz nicht unbedingt gleichwertig : Ein Problem könnte in C wesentlich effizienter gelöst werden als mit Turing-Maschinen. Wenn wir an Effizienz interessiert sind, sollten wir uns auf alle Modelle beschränken, die in Bezug auf die Laufzeit "nah genug" an C sind. Wenn wir zum Beispiel eine Anweisung verwenden dürfen, die berechnet ! In einer Zeiteinheit definiert das resultierende Modell immer noch den gleichen Satz berechenbarer Funktionen, aber einige Funktionen (wie n !n! n! ) kann darin wesentlich effizienter berechnet werden als C.
Wenn wir uns Sorgen über die tatsächlichen Laufzeiten auf einem Computer machen, sollten wir noch vorsichtiger sein, aber dies geht leider normalerweise über die Grenzen der theoretischen Informatik hinaus.
Wenn wir sehr pingelig sind, müssen wir uns über den Unterschied zwischen Algorithmen und Funktionen, die von Algorithmen berechnet werden , im Klaren sein . Beispielsweise erhält die Fakultätsfunktion als Eingabe eine natürliche Zahl und gibt n aus ! . Die Fakultätsfunktion kann durch einen Algorithmus berechnet werden. Wir sagen, dass eine Funktion berechenbar ist, wenn sie mit einem Algorithmus berechnet werden kann.n n!
Welchen Algorithmus sollten wir verwenden? Ein oben dargestellter Vorschlag ist die Verwendung von C-Programmen. Wir können diesen Begriff C-Berechnung nennen. Turing-Berechnung erhalten Sie, wenn Sie Turing-Maschinen verwenden. Es stellt sich heraus, dass eine Funktion genau dann C-berechenbar ist, wenn sie Turing-berechenbar ist. In diesem Sinne sind beide Berechnungsmodelle äquivalent. Tatsächlich sind viele andere Modelle gleichwertig, zum Beispiel alle gängigen Programmiersprachen (mit unendlichem Speicher und unbegrenzten Variablen).
Wir sagen, eine Programmiersprache P ist Turing-vollständig ist eine Funktion, die genau dann P-berechenbar ist, wenn sie Turing-berechenbar ist. Die Church-Turing-Hypothese ist eine informelle Aussage dahingehend, dass alle vernünftigen Rechenmodelle mit endlicher Beschreibung und endlicher Zeitdauer vollständig sind. Ihr Modell hat eine endliche Beschreibung, benötigt aber keine endliche Zeit.
quelle
Der wichtige Teil der allgemeinen Definition eines Algorithmus, der Ihnen fehlt, ist, dass die Spezifikation endlich sein muss und die Größe der Spezifikation nicht mit der Größe der Eingabe variieren darf.
Der Speicher kann beliebig groß sein, ebenso wie Eingaben. Um jedoch einen Algorithmus sinnvoll zu definieren, muss der Codespace endlich sein. Andernfalls erhalten Sie das Problem, das Sie gerade identifiziert haben.
quelle
eval
Funktion für eine gerade erstellte große Datenstruktur aufruft und einen lLisp-Ausdruck darstellt, nicht als Algorithmus betrachtet werden kann. Ich vermute, dass ein Großteil des Codes, der im 20. Jahrhundert am MIT produziert wurde, nicht als Algorithmus qualifiziert ist. Dies ist nur ein informelles Argument, aber das formale Problem liegt in der Ansicht, was eine endliche Spezifikation ist, die Sie viel zu restriktiv lesen.Einige Beobachtungen, die hilfreich sein könnten:
Probleme sind Aussagen über zulässige Eingaben und entsprechende Ausgaben. Sie sind das, was wir lösen wollen. Algorithmen sind Rechenverfahren. Wir können sagen, dass ein Algorithmus in Bezug auf ein Problem korrekt ist, wenn er Eingaben akzeptiert, die in Bezug auf das Problem zulässig sind, und Ausgaben gemäß der Problembeschreibung erzeugt.
Bei beiden Beispielen handelt es sich um Algorithmen, da es sich um eindeutige Berechnungsverfahren handelt. Ob die Algorithmen korrekt sind oder nicht, hängt davon ab, wie Sie das Problem definieren und wie Sie die Darstellung des Algorithmus interpretieren. Einige Problemstellungen:
INT_MAX
Einige Interpretationen Ihres ersten Codeausschnitts:
int
bedeutet wirklich "irgendeine ganze Zahl", zum Beispiel.Interpretation 1 ist für Problemstellung 1 korrekt, solange die Fakultät den Wert 1 für negative Zahlen annimmt (andernfalls könnten wir die Problemstellung ändern, um die Domäne einzuschränken, oder den Algorithmus, um das gewünschte Verhalten zu berücksichtigen). Interpretation 2 ist für Problemstellung 2 mit dem gleichen Vorbehalt korrekt.
array
array
INT_MAX
quelle
Ein Algorithmus ist ein in a geschriebenes Programm Turing-vollständigen Sprache geschrieben ist und nachweislich bei allen gültigen Eingaben anhält. Alle Standard-Programmiersprachen sind Turing-komplett. Das Wort stammt aus einer europäischen Übersetzung des Namens al-Khwārizmī, eines persischen Mathematikers, Astronomen und Geographen, dessen Arbeit auf der des indischen Mathematikers Brahmagupta aus dem 7. Jahrhundert aufbaut, der das indische Zahlensystem in die westliche Welt einführte.
Die Frage scheint grundsätzlich zu sein, ob Nachschlagetabellen Teil von Algorithmen sind. Absolut! In Turing Machines (TM) können Tabellen in die Statustabelle des TMs kodiert werden. Der TM kann das Band basierend auf einer begrenzten Menge von Daten initialisieren, die in der Übergangstabelle gespeichert sind. "Algorithmen", die nicht auf unendlichen Eingaben, sondern nur auf endlichen Eingaben ausgeführt werden, sind jedoch "triviale" Zustandsmaschinen (FSM) .
quelle
Kurz gesagt : Ein Algorithmus ist der konstruktive Teil eines konstruktiven Beweises, dass ein gegebenes Problem eine Lösung hat. Die Motivation für diese Definition ist der Curry-Howard-Isomorphismus zwischen Programmen und Beweisen, wenn man bedenkt, dass ein Programm nur dann ein Interesse hat, wenn es ein Problem löst, aber nachweislich. Diese Definition ermöglicht eine stärkere Abstraktion und lässt einige Türen in Bezug auf die Art der Domänen offen, die möglicherweise betroffen sind, z. B. in Bezug auf Endlichkeitseigenschaften.
Warnung . Ich versuche, einen angemessenen formalen Ansatz für die Beantwortung der Frage zu finden. Ich denke, es ist notwendig, aber es scheint, dass keiner der Benutzer, die bisher geantwortet haben (ich selbst eingeschlossen und einige davon in anderen Posts mehr oder weniger explizit erwähnt), den richtigen Hintergrund hat, um die Probleme, die damit zusammenhängen, richtig zu entwickeln Konstruktive Mathematik, Beweistheorie, Typentheorie und Ergebnisse wie der Curry-Howard-Isomorphismus zwischen Beweisen und Programmen. Ich gebe hier mein Bestes, mit allem Wissen, das ich (glaube) habe, und ich bin mir der Grenzen dieser Antwort nur zu bewusst. Ich hoffe nur, einige Hinweise zu geben, wie die Antwort meiner Meinung nach aussehen sollte. Wenn Sie einen Punkt sehen, der formal (nachweislich) eindeutig falsch ist, lassen Sie es mich jetzt in einem Kommentar - oder per E-Mail - wissen.
Einige Probleme identifizieren
Eine Standardmethode, um einen Algorithmus zu betrachten, besteht darin, anzugeben, dass ein Algorithmus ein beliebiges, endlich festgelegtes Programm für einige Computergeräte ist , einschließlich solcher, die keine Speicherbeschränkungen aufweisen. Die Sprache kann auch die Maschinensprache des Computers sein. Tatsächlich ist es ausreichend, alle Programme für ein Turing-vollständiges Computergerät zu berücksichtigen (was impliziert, dass es keine Speicherbeschränkungen gibt). Möglicherweise erhalten Sie nicht alle Algorithmen in der Form, dass Algorithmen in einer Form ausgedrückt werden müssen, die in ihren Details vom Interpretationskontext abhängt, auch theoretisch, da alles bis zu einer gewissen Kodierung definiert ist. Da es jedoch alles berechnet, was zu berechnen ist, enthält es irgendwie alle Algorithmen bis hin zur Codierung.
Die eigentliche Frage ist also zu wissen, was die sinnvollen Algorithmen sind. Die Antwort ist, dass die aussagekräftigen Algorithmen diejenigen sind, die ein Problem lösen und Schritt für Schritt die "Lösung", die "Antwort", auf dieses Problem berechnen. Ein Algorithmus ist interessant, wenn er mit einem Problem verbunden ist, das er löst.
Wenn wir also ein formales Problem haben, wie bekommen wir einen Algorithmus, der das Problem löst. Unabhängig davon, ob explizit oder implizit, werden Algorithmen mit der Idee verknüpft, dass es eine Lösung für das Problem gibt, die sich als richtig erweisen lässt. Ob unsere Beweistechniken korrekt sind, ist eine andere Frage, aber wir versuchen uns zumindest selbst zu überzeugen. Wenn Sie sich auf konstruktive Mathematik beschränken, was wir eigentlich tun müssen (und für die meisten Mathematiker eine sehr akzeptable axiomatische Einschränkung darstellen), müssen Sie die Existenz einer Lösung anhand von Beweisschritten nachweisen, die tatsächlich ein Konstrukt aufweisen das repräsentiert die Lösung, einschließlich möglicherweise anderer Schritte, die sie auf Richtigkeit überprüfen.
Alle Programmierer denken so etwas wie: Wenn ich mit den Daten so und so herumfummle, bekomme ich dieses Widget, das aufgrund des Satzes von Sesame genau die richtigen Eigenschaften hat, und wenn ich diese foo-erhaltende Transformation durchführe, bekomme ich die gewünschte Antwort . Der Beweis ist jedoch in der Regel informell und wir arbeiten nicht alle Details aus, was erklärt, warum ein Satellit (unter anderem) versucht hat, den Mars im Untergrund zu umkreisen. Wir tun einen Großteil der Neukonstruktion, behalten jedoch nur den konstruktiven Teil bei, der die Lösung erstellt, und beschreiben ihn in einer Computersprache als den Algorithmus, der das Problem löst.
Interessante Algorithmen (oder Programme)
Dies alles war, um die folgenden Ideen einzuführen, die Gegenstand vieler aktueller Forschungen sind (von denen ich kein Spezialist bin). Der hier verwendete Begriff " interessanter Algorithmus " stammt von mir und wurde als informeller Platzhalter für genauere Definitionen eingeführt.
Ein interessanter Algorithmus ist der konstruktive Teil eines konstruktiven Beweises, dass ein gegebenes Problem eine Lösung hat . Das heißt, der Beweis muss die Lösung tatsächlich zeigen, anstatt einfach seine Existenz zu beweisen, zum Beispiel durch Widerspruch. Weitere Einzelheiten finden Sie unter Intuitionistische Logik und Konstruktivismus in der Mathematik.
Dies ist natürlich eine sehr restriktive Definition, die nur das berücksichtigt, was ich interessante Algorithmen nannte. Daher werden fast alle ignoriert. Aber auch alle unsere Lehrbücher zum Thema Algorithmus. Sie versuchen, nur einige der Interessanten zu unterrichten.
Anhand aller Parameter des Problems (Eingabedaten) erfahren Sie Schritt für Schritt, wie Sie ein bestimmtes Ergebnis erhalten. Ein typisches Beispiel ist die Auflösung von Gleichungen (der Name Algorithmus ist eigentlich aus dem Namen eines persischen Mathematiker abgeleitet, Al-Chwarizmi , der die Auflösung einiger Gleichungen untersucht). Teile des Beweises werden verwendet, um festzustellen, dass einige im Algorithmus berechnete Werte bestimmte Eigenschaften haben, diese Teile müssen jedoch nicht im Algorithmus selbst gespeichert werden.
Dies muss natürlich in einem formalisierten logischen Rahmen geschehen, der festlegt, mit welchen Daten gerechnet wird, welche elementaren Rechenschritte zulässig sind und welche Axiome verwendet werden.
Zurück zu Ihrem Fakultätsbeispiel: Es kann als Algorithmus ausgelegt werden, wenn auch als trivialer. Die normale Fakultätsfunktion entspricht einem Beweis dafür, dass es bei gegebenem arithmetischen Rahmen und gegebenem ganzzahligen n eine Zahl gibt, die das Produkt der ersten n ganzen Zahlen ist. Dies ist ziemlich einfach, ebenso wie die Fakultätsberechnung. Für andere Funktionen könnte es komplexer sein.
Wenn Sie sich nun dazu entschließen, Fakultäten zu tabellieren, vorausgesetzt, Sie können dies, was nicht für alle ganzen Zahlen gilt (sondern für einen endlichen Wertebereich gelten könnte), müssen Sie lediglich die Existenz von Fakultäten in Ihre Axiome aufnehmen, indem Sie mit a definieren neue Axiom seinen Wert für jede ganze Zahl, so dass Sie nichts mehr zu beweisen (daher zu berechnen) brauchen.
Aber ein Axiomensystem soll endlich (oder zumindest endlich definiert) sein. Und es gibt unendlich viele Werte für Fakultät, einen pro Ganzzahl. Sie stecken also in Schwierigkeiten mit Ihrem endlichen Axiomensystem, wenn Sie eine unendliche Funktion axiomatisieren, dh auf einer unendlichen Domäne definieren. Dies führt rechnerisch dazu, dass Ihre potenzielle Tabellensuche nicht für alle ganzen Zahlen implementiert werden kann. Das würde die übliche Endlichkeitsanforderung für Algorithmen zunichte machen (aber ist es so streng, wie oft dargestellt?).
Sie könnten sich für einen endlich definierten Axiomgenerator entscheiden, der alle Fälle behandelt. Dies würde mehr oder weniger bedeuten, das standardmäßige Fakultätsprogramm in Ihren Algorithmus aufzunehmen, um das Array nach Bedarf zu initialisieren. Das nennt man Memoisation von Programmierern. Dies ist tatsächlich der Wert, der dem Äquivalent einer vorberechneten Tabelle am nächsten kommt. Es kann verstanden werden, dass eine vorberechnete Tabelle vorhanden ist, mit der Ausnahme, dass die Tabelle tatsächlich im verzögerten Auswertungsmodus erstellt wird , wann immer dies erforderlich ist. Diese Diskussion würde wahrscheinlich ein bisschen formeller sein müssen.
Sie können Ihre primitiven Operationen nach Ihren Wünschen definieren (im Einklang mit Ihrem formalen System) und ihnen die Kosten zuweisen, die Sie bei der Verwendung in einem Algorithmus wählen, um eine Komplexitäts- oder Leistungsanalyse durchzuführen. Wenn jedoch die konkreten Systeme, die Ihren Algorithmus tatsächlich implementieren (z. B. ein Computer oder ein Gehirn), diese Kostenspezifikationen nicht einhalten können, ist Ihre Analyse möglicherweise intellektuell interessant, für die tatsächliche Verwendung in der realen Welt jedoch wertlos.
Welche Programme sind interessant?
Diese Diskussion sollte besser mit Ergebnissen wie dem Curry-Howard-Isomorphismus zwischen Programmen und Beweisen verknüpft werden . Wenn irgendein Programm tatsächlich ein Beweis für etwas ist, kann jedes Programm als interessantes Programm im Sinne der obigen Definition ausgelegt werden.
Nach meinem (eingeschränkten) Verständnis ist dieser Isomorphismus jedoch auf Programme beschränkt, die in einem geeigneten Typisierungssystem gut typisiert werden können, wobei Typen Aussagen der axiomatischen Theorie entsprechen. Daher können nicht alle Programme als interessante Programme eingestuft werden. Ich vermute, dass in diesem Sinne ein Algorithmus ein Problem lösen soll.
Dies schließt wahrscheinlich die meisten "zufällig generierten" Programme aus.
Es ist auch eine etwas offene Definition eines "interessanten Algorithmus". Jedes Programm, das als interessant angesehen werden kann, ist dies auf jeden Fall, da es ein identifiziertes Typensystem gibt, das es interessant macht. Aber ein Programm, das bisher nicht typisierbar war, könnte mit einem fortgeschritteneren Typsystem typisierbar und somit interessant werden. Genauer gesagt war es immer interessant, aber mangels Kenntnis des richtigen Typensystems konnten wir es nicht wissen.
Es ist jedoch bekannt, dass nicht alle Programme typisierbar sind, da bekannt ist, dass einige Lambda-Ausdrücke, z. B. die Implementierung des Y-Kombinators , nicht in ein Soundtyp- System eingegeben werden können .
Diese Ansicht gilt nur für Programmierformalismen, die einem bestimmten axiomatischen Beweissystem direkt zugeordnet werden können. Ich weiß nicht, wie es auf einfache Computerformalismen wie die Turing-Maschine ausgedehnt werden kann. Da Algorithmus und Berechenbarkeit jedoch häufig ein Spiel der Kodierung von Problemen und Lösungen sind (denken Sie an in Lambda-Kalkül kodierte Arithmetik ), kann man davon ausgehen, dass jede formal definierte Berechnung, die als Kodierung eines Algorithmus gezeigt werden kann, auch ein Algorithmus ist. Solche Kodierungen verwenden wahrscheinlich nur einen sehr kleinen Teil dessen, was sich in einem einfachen Formalismus wie Turing Machines ausdrücken lässt.
Ein Interesse dieses Ansatzes besteht darin, dass er einen Begriff eines Algorithmus liefert, der abstrakter und unabhängig von Problemen der tatsächlichen Codierung, der "physischen Repräsentierbarkeit" der Berechnungsdomäne ist. So kann man zum Beispiel Domänen mit unendlichen Objekten betrachten, solange es eine rechnerisch fundierte Möglichkeit gibt, sie zu verwenden.
quelle
Zum Zeitpunkt des Schreibens gibt es keine gute formale Definition von "Algorithmus". Es gibt jedoch clevere Leute, die daran arbeiten.
Was wir wissen, ist, dass, was immer ein "Algorithmus" ist, er irgendwo zwischen "mathematischer Funktion" und "Computerprogramm" liegt.
Eine mathematische Funktion ist der formale Begriff einer Abbildung von Eingaben auf Ausgaben. So ist beispielsweise "sortieren" eine Zuordnung zwischen einer Folge von bestellbaren Artikeln und einer Folge von bestellbaren Artikeln desselben Typs, die jede Folge ihrer bestellbaren Folge zuordnet. Diese Funktion kann mit verschiedenen Algorithmen implementiert werden (zB Mergesort, Heapsort). Jeder Algorithmus könnte wiederum unter Verwendung verschiedener Programme implementiert werden (selbst wenn dieselbe Programmiersprache verwendet wird).
Das Beste, was wir über einen "Algorithmus" wissen, ist, dass es sich um eine Art Äquivalenzklasse für Programme handelt, bei der zwei Programme äquivalent sind, wenn sie "im Wesentlichen dasselbe" tun. Zwei beliebige Programme, die denselben Algorithmus implementieren, müssen dieselbe Funktion berechnen, aber die Umkehrung ist nicht wahr.
Ebenso gibt es eine Äquivalenzklasse zwischen Algorithmen, bei der zwei Algorithmen äquivalent sind, wenn sie dieselbe mathematische Funktion berechnen.
Das Schwierige dabei ist, das zu erfassen, was wir unter "im Wesentlichen dasselbe" verstehen.
Es gibt einige offensichtliche Dinge, die wir einbeziehen sollten. Beispielsweise sind zwei Programme im Wesentlichen gleich, wenn sie sich nur durch variable Umbenennungen unterscheiden. Die meisten Modelle von Programmiersprachen haben native Vorstellungen von "Äquivalenz" (z. B. Beta-Reduktion und Eta-Konvertierung in Lambda-Kalkül), daher sollten wir diese auch einwerfen.
Welche Äquivalenzbeziehung wir auch wählen, dies gibt uns eine gewisse Struktur. Algorithmen bilden eine Kategorie, weil sie die Quotientenkategorie von Programmen sind. Es ist bekannt, dass einige interessante äquivalente Beziehungen interessante kategoriale Strukturen hervorrufen. Beispielsweise ist die Kategorie der primitiven rekursiven Algorithmen ein universelles Objekt in der Kategorie der Kategorien. Wann immer Sie interessante Strukturen wie diese sehen, wissen Sie, dass diese Art der Untersuchung wahrscheinlich nützlich sein wird.
quelle
Ihre Frage und Beschreibung beziehen sich nicht so sehr. Der Algorithmus ist theoretisch und bezieht sich nicht auf eine Programmiersprache. Algorithmus ist ein Satz von Regeln oder Schritten (Prozeduren), um ein Problem zu lösen. Ihr Problem kann auf viele Arten oder mit vielen Algorithmen gelöst werden.
Ihre zweite Lösung besteht darin, zunächst eine große Anzahl von Fakultäten zu berechnen, die zunächst viel Zeit in Anspruch nehmen und dann speichern. Es wird mehr Speicherplatz verbrauchen, aber irgendwann wird es schneller, während das erste nicht Speicherplatz verbraucht, sondern Rechenleistung verbraucht, sodass Sie je nach Ihrer Umgebung wählen müssen.
quelle