java – Clojure中的时间素数生成
这对于真正熟悉Clojure的人来说是一个问题.
我想在 Java和Clojure中编写简单的素数检查函数,并比较执行时间. 所以这是我在Java中的代码: import java.util.LinkedList; public class Primes { public static void main(String args[]) { long start = System.nanoTime(); getPrimes(10000); long end = System.nanoTime(); System.out.println(((float)(end - start)/1000000) + "ms"); } private static LinkedList<Integer> getPrimes(int n) { int count = 0; int current = 1; LinkedList<Integer> primes = new LinkedList<Integer>(); while(count <= n) { if(isPrime(current)) { primes.add(current); count++; } current++; } return primes; } private static boolean isPrime(long n) { if(n <= 0) return false; if(n == 1 || n == 2) return true; if(n % 2 == 0) return false; for(int i=3; i<Math.sqrt(n) + 1; i=i+2) { if(n % i == 0){ return false; } } return true; } } 这是Clojure的等价物: (defn prime? [n] (or (= n 2) (not (some #(zero? (rem n %)) (conj (range 3 (inc (Math/sqrt n)) 2) 2))))) (defn printPrimes [n] (take n (filter prime? (iterate inc 1)))) (defn ExecTime [function & arguments] (let [start (System/nanoTime),return (dorun (apply function arguments)),end (System/nanoTime)] (/ (- end start) 1000000.0))) (ExecTime printPrimes 10000) 现在有一些我不确定的事情: >是(let)和绑定开始和结束时间可以测量Clojure中的执行时间吗? 如果我犯了一些明显的错误,请原谅我的无知,但我仍处于Clojure的学习阶段…… – – -编辑 – – – 我对它进行了优化,最终实现了与Java相同的时间.我在我的博客中描述了感兴趣的人: 解决方法
也许它正在处理懒惰的seqs作为上面提到的答案.这是我的证据……
;; original prime? function (defn prime? [n] (or (= n 2) (not (some #(zero? (rem n %)) (conj (range 3 (inc (Math/sqrt n)) 2) 2))))) ;; prime? function using recur (defn prime?-recur [num] (cond (< num 2) false (= num 2) true (zero? (mod num 2)) false :else (loop [n num i 3] (cond (>= i (inc (Math/sqrt n))) true (zero? (mod n i)) false (< i (inc (Math/sqrt n))) (recur n (+ i 2)))))) ;; original printPrimes with option for testing both prime? funs ;; note I changed this to start on 2 since 1 is not prime (defn printPrimes [n fn] (take n (filter fn (iterate inc 2)))) ;; printPrimes using recursion (defn printPrimes-recur [num fn] (loop [n num i 2 primes []] (cond (and (fn i) (< (count primes) n)) (recur n (+ i 1) (conj primes i)) (< (count primes) n) (recur n (+ i 1) primes) :else primes))) 现在,让我们运行这些.首先只是为了确保新代码与原始代码匹配: foo> (= (printPrimes 10000 prime?) (printPrimes 10000 prime?-recur) (printPrimes-recur 10000 prime?) (printPrimes-recur 10000 prime?-recur)) true 现在有一段时间了! (使用您的ExecTime功能) foo> (println (ExecTime printPrimes 10000 prime?) (ExecTime printPrimes 10000 prime?-recur) (ExecTime printPrimes-recur 10000 prime?) (ExecTime printPrimes-recur 10000 prime?-recur)) 575.977 166.691 548.363 141.356 nil 所以我们看到改变素数?使用递归的函数会产生很大的差异(大约快4倍),并且更改printPrimes函数以使用递归也会产生差异,但它只是一个微小的差异.我不确定java版本在我的计算机上占用多长时间,但你至少可以从上面的时间看到循环/复现版本似乎比使用seqs的原始clojure版本更快. 注意:您也可以尝试输入提示(http://clojure.org/java_interop#Java%20Interop-Type%20Hints,http://kotka.de/blog/2012/06/Did_you_know_IX.html)以提高速度,但是当我尝试时,它没有任何区别.那可能是因为我之前没有做过多少,所以我本可以做得不好. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |