2017-10-15 14 views
0

OCamlでより速いバージョンの指数関数を見つけるのが難しいです。ここで私は従うことをしようとしているいくつかの注意事項は次のとおりです。高速指数関数を作成する

  1. ではなくexpt b n ==> b * (b * (b ...)の典型的な再帰的な指数のバージョンは、この機能は、B二つの引数を受け取り、nおよび基本的に分割統治スタンスを取ります。
  2. nが偶数の場合、nが、その後fastexpt b n => b * (b^(n - 1))

奇数の場合は、その後、他のfastexpt b n => (b^(n/2))^2は、ここで私はこれまでに書いたコードです:

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));; 

は、私の質問は:書き込みする方法はありますが、 expt機能を使用しないでこの機能を使用できますか? (私たちは、あなたがすでにexptを宣言したことを考慮すれば)何がここでやっていることは除算を使用して方法を最初に征服した後、残りの計算のための通常のものを使用している

+2

を使用し、 '? –

+0

おそらく私はOCamlの言語をあまりよく理解していませんが、もしfastexptを含めるなら、私はfastexptの最初の定義を "let rec"とする必要はありませんか? – Sean

+1

@Sean、https://stackoverflow.com/help/how-to-askから: **質問を投稿してフィードバックにお答えください 投稿した後、少し質問をブラウザに残しておきます誰かがコメントしたら。明白な情報が欠けている場合は、質問を編集して対応する準備をしてください。 ** 質問をするときは、回答を受け入れ、コメントや回答に答えてください。あなたの質問には、奇妙な答えはありません。失礼しないでください。人々はここで助けてくれる、出かないで通信しないでください。 – Lhooq

答えて

1

もう一つは、ということですnが奇数の場合、高速累乗の目的はb * b^((n-1)/2) * b^((n-1)/2)です。

あなただけの再帰としてfastexptを定義し、それをすべての方法を使用されて何をすべき:fastexpt`代わり

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

もし指数関数的に高速化しようとしているのであれば、CPU上の遅い命令なので、 'mod'と除算を避けることができます。代わりに、2の累乗で整数除算にビットシフト演算を使用し、ビット演算を使用して数値のパリティをテストすることができます。第1ビットがゼロに設定されている場合、数値は偶数です。しかし、OCamlコンパイラが既にこれらの最適化を行っている可能性はありますが、試してみる価値があります。 –

+0

はい、ありがとうございます、私は実際にはアルゴリズム的な観点から答えていましたが、貴重な点は注目に値します。 ;-) – Lhooq

+1

@AnthonyScemamaコンパイラはこれらの最適化を行います。あなたが最適性を望むなら、あなたの整数が計算中にボックス化されていないことを保証するために暗い魔法があるかもしれません(私はそれが手動で実行可能であるかどうかはわかりませんが)。 – PatJ

関連する問題