2017-06-05 3 views
3

Ich habe eine sehr einfache Funktion und ich möchte ein Programm schreiben, das f für jeden n = 1,2,...,max aufruft. Nach jedem Aufruf von f sollte die bis dahin verwendete (kumulierte) Zeit angezeigt werden (zusammen mit n und f n). Wie kann dies umgesetzt werden?Wiederholtes Timing der Funktion

Ich bin immer noch wirklich neu zu Eingabe/Ausgabe in Haskell, so ist dies, was ich bisher versucht (mit etwas Spielzeug Beispielfunktion f)

f :: Int -> Int 
f n = sum [1..n] 

evalAndTimeFirstN :: Int -> Int -> Int -> IO() 
evalAndTimeFirstN n max time = 
    if n == max 
    then return() -- in the following we have to calculate the time difference from start to now 
    else let str = ("(" ++ (show n) ++ ", " ++ (show $ f n) ++ ", "++ (show time)++ ")\n") 
     in putStrLn str >> evalAndTimeFirstN (n+1) max time -- here we have to calculate the time difference 

main :: IO() 
main = evalAndTimeFirstN 1 5 0 

ich recht sehe nicht, wie ich Ich muss das Timing hier vorstellen. (Die Int für time muss wahrscheinlich durch etwas anderes ersetzt werden.)

+4

Es ist wahrscheinlich besser, Benchmarking an ein spezialisiertes Tool, z. http://www.serpentine.com/criterion/ – karakfa

+0

Vielen Dank für diesen Link! Es scheint mir ein bisschen zu schwierig zu sein, also denke ich, dass ich immer noch versuche, einen grundlegenden Ansatz zu verfolgen, bevor ich solche Bibliotheken benutze, weil ich lernen will, wie man so denkt. – flawr

+2

Es ist schwierig, Benchmarking richtig und doppelt so in einer faulen Sprache durchzuführen. Wenn Sie genaue Ergebnisse wünschen, empfehle ich nicht, Ihre eigenen zu rollen. –

Antwort

0

Endlich habe ich eine Lösung gefunden. In diesem Fall messen wir die "reale" Zeit in ms.

import Data.Time 
import Data.Time.Clock.POSIX 

f n = sum[0..n] 

getTime = getCurrentTime >>= pure . (1000*) . utcTimeToPOSIXSeconds >>= pure . round 

main = do 
    maxns <- getLine 
    let maxn = (read maxns)::Int 
    t0 <- getTime 
    loop 1 maxn t0 
    where loop n maxn t0|n==maxn = return() 
      loop n maxn t0 
      = do 
       putStrLn $ "fun eval: " ++ (show n) ++ ", " ++ (show $ (f n)) 
       t <- getTime 
       putStrLn $ "time: " ++ show (t-t0); 
       loop (n+1) maxn t0 
0

Sie wollen wahrscheinlich so etwas. Passen Sie das folgende grundlegende Beispiel für Ihre rekursive Funktion an.

import Data.Time.Clock 
import Control.Exception (evaluate) 

main :: IO() 
main = do 
    putStrLn "Enter a number" 
    n <- readLn 
    start <- getCurrentTime 
    let fact = product [1..n] :: Integer 
    evaluate fact -- this is needed, otherwise laziness would postpone the evaluation 
    end <- getCurrentTime 
    putStrLn $ "Time elapsed: " ++ show (diffUTCTime end start) 
    -- putStrLn $ "The result was " ++ show fact 

Kommentar- die letzte Zeile das Ergebnis (es wird sehr groß sehr schnell) zu drucken.

+0

Ich habe Schnipsel wie dieses bisher gefunden, aber ich sehe nicht, wie man das anwendet, wenn man die Zeiten für alle "n = 1,2, ..., max" und nicht nur für einen "Slinge" messen will n ', also würde man eine Art' Schleife 'über diesen 'n' brauchen, aber das ist der Punkt, an dem ich feststecke. – flawr

+0

@flawr Aber Ihr eigener Code macht eine solche Schleife, die Rekursion verwendet. Es ist wahrscheinlich nicht der beste Stil, aber es funktioniert. Ich würde die Aufrufe von "getCurrentTime" in Ihrem Code einführen. – chi