在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試一下。