Ich versuche, die e- Konstante ( AKA Euler's Number ) durch Berechnung der Formel zu berechnen
Um die Fakultät und die Division in einem Schuss zu berechnen, habe ich Folgendes geschrieben:
my @e = 1, { state $a=1; 1 / ($_ * $a++) } ... *;
say reduce * + * , @e[^10];
Aber es hat nicht geklappt. Wie mache ich das richtig?
code-generation
lazy-evaluation
raku
eulers-number
Lars Malmsteen
quelle
quelle
$_
Wertvariable verwendet hat, um die Fakultät zu konstruieren. Es war offensichtlich überflüssig. In der richtigen Lösung unten$_
wurde fallen gelassen und es hat perfekt geklappt.Antworten:
Ich analysiere Ihren Code im Abschnitt Analysieren Ihres Codes . Vorher präsentiere ich ein paar lustige Abschnitte mit Bonusmaterial.
Ein LinerEin Buchstabe 1"Eine Abhandlung über mehrere Wege" 2
Klicken Sie auf den obigen Link, um Damian Conways außergewöhnlichen Artikel über Computer
e
in Raku zu lesen.Der Artikel macht viel Spaß (schließlich ist es Damian). Es ist eine sehr verständliche Diskussion über Computer
e
. Und es ist eine Hommage an Rakus Bikarbonat-Reinkarnation der von Larry Wall vertretenen TIMTOWTDI-Philosophie. 3Als Vorspeise hier ein Zitat aus der Mitte des Artikels:
Analysieren Sie Ihren Code
Hier ist die erste Zeile, in der die Serie generiert wird:
Der Abschluss (
{ code goes here }
) berechnet einen Begriff. Ein Abschluss hat eine implizite oder explizite Signatur, die bestimmt, wie viele Argumente er akzeptiert. In diesem Fall gibt es keine explizite Signatur. Die Verwendung von$_
( der Variablen "topic" ) führt zu einer impliziten Signatur, für die ein Argument erforderlich ist, an das gebunden ist$_
.Der Sequenzoperator (
...
) ruft wiederholt den Abschluss auf der linken Seite auf und übergibt den vorherigen Begriff als Argument des Abschlusses, um träge eine Reihe von Begriffen bis zum Endpunkt auf der rechten Seite zu erstellen, in diesem Fall*
Abkürzung fürInf
aka Infinity.Das Thema im ersten Aufruf zur Schließung ist
1
. Der Abschluss berechnet und gibt also1 / (1 * 1)
die ersten beiden Terme der Reihe als zurück1, 1/1
.Das Thema im zweiten Aufruf ist der Wert des vorherigen
1/1
, dh1
erneut. Der Abschluss berechnet und kehrt zurück1 / (1 * 2)
und erweitert die Serie auf1, 1/1, 1/2
. Es sieht alles gut aus.Der nächste Abschluss berechnet,
1 / (1/2 * 3)
welches ist0.666667
. Dieser Begriff sollte sein1 / (1 * 2 * 3)
. Hoppla.Passen Sie Ihren Code an die Formel an
Ihr Code soll mit der Formel übereinstimmen:
In dieser Formel wird jeder Term basierend auf seiner Position in der Reihe berechnet . Der k- te Term in der Reihe (wobei k = 0 für den ersten ist
1
) ist nur der Kehrwert von Fakultät k .(Es hat also nichts mit dem Wert des vorherigen Terms zu tun . Daher
$_
sollte der Wert , der den Wert des vorherigen Terms erhält , nicht für den Abschluss verwendet werden.)Erstellen wir einen faktoriellen Postfix-Operator:
(
×
ist ein Infix-Multiplikationsoperator, ein besser aussehender Unicode-Alias des üblichen ASCII-Infix*
.)Das ist eine Abkürzung für:
(Ich habe die pseudometasyntaktische Notation in geschweiften Klammern verwendet, um die Idee zu kennzeichnen, so viele Begriffe wie erforderlich zu addieren oder zu subtrahieren.
Im Allgemeinen bildet das Setzen eines Infix-Operators
op
in eckige Klammern am Anfang eines Ausdrucks einen zusammengesetzten Präfix-Operator, der dem entsprichtreduce with => &[op],
. Weitere Informationen finden Sie unter Reduktions-Metaoperator .Jetzt können wir den Abschluss neu schreiben, um den neuen faktoriellen Postfix-Operator zu verwenden:
Bingo. Dies ergibt die richtige Serie.
... bis es aus einem anderen Grund nicht mehr geht. Das nächste Problem ist die numerische Genauigkeit. Aber lassen Sie uns das im nächsten Abschnitt behandeln.
Ein Einzeiler, der von Ihrem Code abgeleitet ist
Vielleicht komprimieren Sie die drei Zeilen auf eine:
.[^10]
gilt für das Thema, das von der festgelegt wirdgiven
. (^10
ist eine Abkürzung für0..9
, daher berechnet der obige Code die Summe der ersten zehn Terme in der Reihe.)Ich habe
$a
das nächste Semester aus dem Closure Computing gestrichen . Ein einsamer$
ist der gleiche wie(state $)
ein anonymer Zustandsskalar. Ich habe es zu einem Pre-Inkrement anstatt zu einem Post-Inkrement gemacht, um den gleichen Effekt wie bei der Initialisierung$a
von zu erzielen1
.Wir haben jetzt das letzte (große!) Problem, auf das Sie in einem Kommentar unten hingewiesen haben.
Vorausgesetzt, keiner seiner Operanden ist ein
Num
(ein Float und somit ungefähr), gibt der/
Operator normalerweise eine 100% ige Genauigkeit zurückRat
(ein rationales Rational mit begrenzter Genauigkeit). Wenn der Nenner des Ergebnisses jedoch 64 Bit überschreitet, wird dieses Ergebnis in a umgewandelt,Num
das die Leistung gegen Genauigkeit eintauscht, ein Kompromiss, den wir nicht eingehen möchten. Das müssen wir berücksichtigen.Um eine unbegrenzte Genauigkeit sowie eine 100% ige Genauigkeit festzulegen , zwingen Sie die Operation einfach zur Verwendung von
FatRat
s. Um dies richtig zu machen, machen Sie einfach (mindestens) einen der Operanden zu einemFatRat
(und keinen anderen zu einemNum
):Ich habe dies auf 500 Dezimalstellen überprüft. Ich erwarte, dass es genau bleibt, bis das Programm abstürzt, weil ein Limit der Raku-Sprache oder des Rakudo-Compilers überschritten wird. (Siehe meine Antwort auf Kann 65536 Bit breites Bigint nicht in native Ganzzahl entpacken, um eine Diskussion darüber zu erhalten.)
Fußnoten
1 Raku hat einige wichtige mathematische Konstanten eingebaut, einschließlich
e
,i
undpi
(und dessen Aliasπ
). So kann man Eulers Identität in Raku so schreiben, wie es in Mathematikbüchern aussieht. Mit Anerkennung für RosettaCodes Raku-Eintrag für Eulers Identität :2 Damians Artikel ist ein Muss. Aber es ist nur eine von mehreren bewundernswerten Behandlungen, die zu den über 100 Übereinstimmungen für ein Google für "Raku" Eulernummer "gehören .
3 Siehe TIMTOWTDI vs TSBO-Apoo-OWTDI für eine der ausgeglicheneren Blick auf TIMTOWTDI von einem Fan von Python geschrieben. Aber es gibt Nachteile, TIMTOWTDI zu weit zu bringen. Um diese letztere "Gefahr" widerzuspiegeln, prägte die Perl-Community die humorvoll lange, unlesbare und untertriebene TIMTOWTDIBSCINABTE - Es gibt mehr als einen Weg, dies zu tun, aber manchmal ist Konsistenz auch keine schlechte Sache, ausgesprochen "Tim Toady Bicarbonate". Seltsamerweise verwendete Larry Bicarbonat auf Rakus Design und Damian wendete es auf das Rechnen
e
in Raku an.quelle
$
eine Abkürzung iststate $
, es ist ziemlich praktisch.e
für die 3. Lösung anzugeben (mit dem Titel Mein Weg basierend auf Ihrem Weg )? Ich habe versucht, FatRat (500) neben 1 in: hinzuzufügen... given 1.FatRat(500), ...
, um die Zahlen auf 500 Stellen genau zu machen, aber es hat nicht funktioniert.FatRat
Frage im letzten Abschnitt angesprochen . Ich habe auch die ganze Antwort verfeinert, obwohl die einzige große Änderung dasFatRat
Zeug ist. (Übrigens ist mir klar, dass ein Großteil meiner Antwort wirklich tangential zu Ihrer ursprünglichen Frage ist. Ich vertraue darauf, dass es Ihnen nichts ausgemacht hat, all die zusätzlichen Flusen zu schreiben, um mich selbst zu unterhalten und vielleicht für spätere Leser interessant zu sein.).FatRat
Erweiterung muss also in den Codegenerator eingefügt werden. Jetzt habe ich es mitFatRat
dieser Methode versucht und es hat das e auf die Genauigkeit von über 1000 Stellen berechnet . Der zusätzliche Flaum ist währenddessen wert. Zum Beispiel wusste ich nicht, dass dassay
die langen Arrays / Sequenzen abschneidet. Solche Informationen sind gut zu wissen..FatRat
Erweiterung muss also in den Codegenerator eingefügt werden." Ja. Wenn ein Ausdruck, der eine Teilung beinhaltet, bereits ausgewertet wurde, ist es im Allgemeinen zu spät, um den Schaden rückgängig zu machen, der verursacht wurde, wenn dieRat
Genauigkeit des Überlaufs überschritten wurde. Wenn dies der Fall ist, wird es zu einemNum
(float) ausgewertet, was wiederum alle weiteren damit verbundenen Berechnungen beeinträchtigt und diese ebenfalls ergibtNum
. Der einzige Weg, um sicherzustellen, dass die Dinge bleiben,FatRat
besteht darin , sie zu startenFatRat
undNum
s zu vermeiden .Int
s undRat
s sind in Ordnung, vorausgesetzt, es gibt mindestens eineFatRat
, die Raku wissen lässt, dass sie sich anFatRat
s halten soll.Es gibt Brüche in
$_
. Also brauchst du1 / (1/$_ * $a++)
oder eher$_ /$a++
.Mit Raku können Sie diese Berechnung Schritt für Schritt durchführen
quelle
andthen
.