groovy: 也來玩玩梅森數

在javaeye的ruby版,看見ruby算梅森數組的一個貼,

http://www.iteye.com/topic/362901

很有趣啊。

我這裏弄一個groovy的實現。

什麼是梅森數組:

http://zh.wikipedia.org/w/index.php?title=%E6%A2%85%E6%A3%AE%E7%B4%A0%E6%95%B0&variant=zh-cn

 

給一個原始的實現:

boolean isPrime(n)


 { 


    if(n==1) return false;


    if(n==2) return true;


     for(i in 2..Math.round(n**(0.5))){println i;if(n%i==0) return false}


     return true;


 }





mersennes = [];


(2..31).each{n=2**(it)-1;if(isPrime(n)) mersennes << n}


println mersennes;
 


我的機器耗時2秒算到n=31的梅森數2147483647
,達到歐拉的水平. O^O
之後就很難了, 等了5分鐘也沒算出下一個梅森數。
繼續優化:

算法分析:
f(n)=2**n-1
f(n+1)=2**(n+1)-1=(2**n)*2-1=(2**n)*2-2+1=2(2**n-1)+1=2f(n)+1

==>
f(n+1)=2f(n)+1

eg:
f(1)=2**1-1=1
f(2)=2*f(1)+1=3
f(3)=2f(2)+1=7
f(4)=2f(3)+1=15
...

於是,代碼如下,注意:加入了一個cache, 存放已經運算出來的f(n):

 boolean isPrime(n)
 { 
    if(n==1) return false;
    if(n==2) return true;
     for(i in 2..Math.round(n**(0.5))){if(n%i==0) return false}
     return true;
 }

cache = new HashMap();

def function(n)
{
    if(cache.getAt(n)!=null) return cache.getAt(n)
    value = (n==1?1:2*function(n-1)+1)
    cache.putAt(n, value);   
    return value;
}

(2..31).each{v=function(it);if(isPrime(v)) println "f"+it+"="+v}
 


還是算到f31, 用時200毫秒,速度提高了一個數量級。
f61還是出不來。
大數據在groovy中默認爲double的, 估計要換成BigDecimal試一下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章