2017-10-15 6 views
0

Ich habe Probleme, eine schnellere Version der typischen Exponentenfunktion in OCaml zu finden. Hier sind einige Richtlinien, die ich zu folgen bin versucht:Erstellen einer schnellen Exponentenfunktion

  1. Anstatt die typische rekursive Exponent Version von expt b n ==> b * (b * (b ...) diese Funktion erhält zwei Argumente b und n und nimmt grundsätzlich eine Kluft und Haltung erobern.
  2. Wenn n gerade ist, dann fastexpt b n => (b^(n/2))^2 sonst, wenn n ungerade ist dann fastexpt b n => b * (b^(n - 1))

Hier ist der Code, den ich geschrieben habe, so weit:

let fastexpt : int -> int -> int 
= fun b n -> 
    if n = 0 then 1 
    else if ((n mod 2) = 0) then (expt b (n/2)) * (expt b (n/2)) 
    else b * (expt b (n - 1));; 

Meine Frage ist: Gibt es eine Möglichkeit zu schreiben diese Funktion ohne die expt Funktion zu verwenden?

+2

Verwenden 'fastexpt' statt? –

+0

Vielleicht verstehe ich die OCaml-Sprache nicht so gut, aber wenn ich fastexpt einbinden müsste, müsste ich dann nicht die anfängliche Definition von "fastexpt" als "let rec" definieren? – Sean

+1

@Sean, von https://Stackoverflow.com/help/how-to-ask: ** Stellen Sie die Frage und reagieren Sie auf Feedback Nach dem Post, lassen Sie die Frage in Ihrem Browser für ein bisschen offen, und sehen wenn jemand Kommentare gibt. Wenn Sie eine offensichtliche Information verpasst haben, seien Sie bereit, zu antworten, indem Sie Ihre Frage bearbeiten, um sie aufzunehmen. Wenn jemand eine Antwort postet, sei bereit, es auszuprobieren und Feedback zu geben! ** Bitte, wenn Sie eine Frage stellen, Antworten akzeptieren und auf Kommentare oder Antworten antworten. Alle deine Fragen haben keine akzeptierte Antwort, was merkwürdig ist. Sei nicht unhöflich, die Leute sind hier, um zu helfen, geh nicht und kommuniziere. – Lhooq

Antwort

1

Was Sie hier machen die Kluft verwendet, und Verfahren zum ersten Mal erobern und dann für den Rest der Berechnung der normalen Verwendung (wenn man bedenkt, dass Sie bereits expt erklärt)

Eine andere Sache ist, dass Wenn n ungerade ist, können Sie b * b^((n-1)/2) * b^((n-1)/2) zurückgeben, das ist der Zweck der schnellen Potenzierung.

Was Sie tun sollten, ist nur fastexpt als rekursiv definieren und verwenden Sie es den ganzen Weg:

let rec fastexpt : int -> int -> int 
= fun b n -> 
    if n = 0 then 1 
    else 
     let b2 = fastexpt b (n/2) in 
     if n mod 2 = 0 then b2 * b2 
     else b * b2 * b2;; 
+3

Wenn Sie versuchen, eine schnelle Exponentialfunktion zu haben, können Sie versuchen, 'mod' und Divisionen zu vermeiden, da diese Anweisungen langsam auf der CPU sind. Stattdessen können Sie Bit-Shift-Operationen für Ganzzahldivision mit einer Potenz von 2 verwenden und Bitoperationen verwenden, um die Parität der Zahl zu testen: Wenn das 1. Bit auf Null gesetzt ist, ist die Anzahl gerade. Es ist jedoch möglich, dass der OCaml-Compiler diese Optimierungen bereits durchführt, aber es ist einen Versuch wert. –

+0

Ja, danke, ich habe tatsächlich aus algorithmischer Sicht geantwortet, aber Ihr Punkt ist erwähnenswert. ;-) – Lhooq

+1

@AnthonyScemama Der Compiler macht diese Optimierungen. Wenn Sie Optimalität wünschen, kann es dunkle Magie geben, um sicherzustellen, dass Ihre Ganzzahlen während der Berechnung nicht gebunden sind (obwohl ich mir nicht sicher bin, ob es manuell machbar ist). – PatJ