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)以提高速度,但是当我尝试时,它没有任何区别.那可能是因为我之前没有做过多少,所以我本可以做得不好. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
