2012-02-23 8 views
2

ここに問題があります。私は別の関数を使ってf#で関数の時間を計る必要があります。私は、引数として持つ根本的に間違っている おそらく何かをタプル(S、N)を取る関数アッカーマンを持って fで任意の関数を時間を計る方法#

time ackermann (2,9);; 

を言って呼び出ししようとしているコード

let time f a = 
    let start = System.DateTime.Now in 
    let res = (fun f a -> f(a)) in 
    let finish = System.DateTime.Now in 
    (res, finish - start) 

のこの作品を持っていますこれは私が解決策から遠く離れているとは思えません。

提案がありますか?

Oh btw。エラーメッセージは次のようになります。

stdin(19,1):エラーFS0030:値の制限。値 'it'は、汎用タイプ を持つと推測されています。(( '' _a - > '_b) - >' _a - > '_b)* System.TimeSpan
' it 'を単純データ用語明示的な引数を持つ関数にするか、汎用的でない場合は型の注釈を追加します。

+3

あなたの質問には関係ありませんが、[Ackermann関数](http://en.wikipedia.org/wiki/Ackermann_function )は、計算可能であるがプリミティブではない再帰関数の総称的な例である。この関数の実行時間を測定することは悪い考えです:) – pad

答えて

7

あなたは、少なくとも二つの問題があります。

  1. let res = f aを試してみてください。範囲内にすでにfaの値がありますが、現在resを新しいfとし、新しいaに適用する関数として定義しています。
  2. DateTime(日付と時刻を表すのに適していますが、短期間を表すのには適していません)を使用しないでください。代わりにSystem.Diagnostics.Stopwatchを使用する必要があります。

    let time f = 
        let sw = System.Diagnostics.Stopwatch.StartNew() 
        let r = f() 
        sw.Stop() 
        printfn "%O" sw.Elapsed 
        r 
    

    使用FSIする原料の束を送信するとき、私は通常私のコードファイルに次のように続ける

    time (fun() -> System.Threading.Thread.Sleep(100)) 
    

+0

は仕事をしました!ありがとうございました! – PNS

+0

これはすべての機能で動作しますか?つまり、 'f'関数に2つまたは3つのパラメータがあるのはどうですか?多分私の質問はばかげていますが、私はF#と関数型プログラミングでは新しくなっています –

+1

@Tom - 引数がタプル( 'f(1,2)'のような)であれば、これはうまくいきます。しかし、 ( 'f 1 2'のように)タイミング関数の別バージョンを書く必要があります。 – kvb

6

あなたはこのような何かを行うことができます。

ビルトインだけ実行時間以上のものを提供するタイミング、FSI年代をオン
#if INTERACTIVE 
#time "on" 
#endif 

Real: 00:00:00.099, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
+0

'f'関数がいくつかのパラメータを持っているのはどうですか...私は' time Fibonacci 23'のようなことをすることができますか? –

+0

@Tom:ラムダを使う必要があります: 'time(fun() - > Fibonacci 23)' – Daniel

2

私はこのようにそれを行うだろう:

let time f = fun a -> 
    let start = System.DateTime.Now 
    let res = f a 
    (res, System.DateTime.Now - start) 

あなたはそれを使用することができます例えば時限関数を作成する

let timedAckermann = time ackermann 
let (res, period) = timedAckermann (2,9) 

また、代わりにDateTime秒のタイミングのためSystem.Diagnostics.Stopwatchを使用することを検討すべきです。

+0

これはかなりスマートです。あなたは、これが することが好ましい理由について詳しく説明できた= F時間は= System.DateTime.Now 始めましょうしましょう (RES、System.DateTime.Now - 開始)は、f RESの=を聞かせて ? hmmはコメントのコードのようには見えません。p – PNS

+0

@PNS - あなたのバージョンは本質的に同じで、おそらく私の答えよりも優れています - あなたのバージョンに暗黙の関数を返すことについては明白です。 – Lee

1

すでに提案したように、この種のタイミング解析には、DateTimeではなくStopwatchを使用する必要があります。

何も言及されていないのは、何らかの理由でDateTimeを使用する必要がある場合は、常にDateTimeではなくDateTime.UtcNowを使用することを検討することです。今。 DateTime.Nowの実装は、 "DateTime.UtcNow.ToLocalTime()"と言い換えることができます。また、 "ToLocalTime()"の部分は、あなたが思う以上のことをしています。オーバーヘッドが少ないだけでなく、DateTime.UtcNowは夏時間に関する頭痛も回避します。いくつかの記事とblog postsがウェブ上でDateTime.NowとDateTime.UtcNowの違いについて調べることができます

関連する問題