加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – Clojure中的时间素数生成

发布时间:2020-12-15 04:08:16 所属栏目:Java 来源:网络整理
导读:这对于真正熟悉Clojure的人来说是一个问题. 我想在 Java和Clojure中编写简单的素数检查函数,并比较执行时间. 所以这是我在Java中的代码: import java.util.LinkedList;public class Primes {public static void main(String args[]){ long start = System.n
这对于真正熟悉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中的执行时间吗?
>出于某种原因(即使Java和Clojure版本使用相同的算法),Clojure版本要慢得多(J:~50ms,C:~400ms).难道我做错了什么?

如果我犯了一些明显的错误,请原谅我的无知,但我仍处于Clojure的学习阶段……

– – -编辑 – – –

我对它进行了优化,最终实现了与Java相同的时间.我在我的博客中描述了感兴趣的人:
http://blog.programmingdan.com/?p=35

解决方法

也许它正在处理懒惰的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)以提高速度,但是当我尝试时,它没有任何区别.那可能是因为我之前没有做过多少,所以我本可以做得不好.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读