F(n) = F(n-1) + F(n-2) F(0) = 0 F(1) = 1
0,1,1,2,3,5,8,13,21,34,55,89,...
package com.snail.exam.aj.fibonacci;
public class Fibonacci {
public static void main(String[] args){
for( int n = 0 ; n < 50 ; n++ ){
double now = System.currentTimeMillis() * 1000000.0 + System.nanoTime();
long fn = fibonacci(n);
double end = System.currentTimeMillis() * 1000000.0 + System.nanoTime();
System.out.println( n + ",F(" + n + ")=" + fn + "," + (end - now)/1000000000.0);
}
}
public static long fibonacci(int n){
if( n == 0 ){
return 0;
}
if( n == 1 ){
return 1;
}
return fibonacci(n-2) + fibonacci(n-1);
}
}
このプログラムは非常に遅いあんまり遅いので、Fibonacci#fibonacci(n) の結果をキャッシングする Aspect を適用する。
package com.snail.exam.aj.fibonacci;
import java.util.LinkedHashMap;
import java.util.Map;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class FibonacciCache {
private static final int MAX_ENTRIES = 2;
private static Map<Integer,Long> cache = new LinkedHashMap<Integer,Long>(){
@Override
protected boolean removeEldestEntry(Map.Entry<Integer,Long> eldest) {
return size() > MAX_ENTRIES;
}
};
public static int getCacheSize(){
return cache.size();
}
@Around("call(long com.snail.exam.aj.fibonacci.Fibonacci.fibonacci(int))")
public long cacheFibonacci(ProceedingJoinPoint thisJoinPoint) throws Throwable{
Object[] args = thisJoinPoint.getArgs();
Integer arg = (Integer)args[0];
if(!cache.containsKey(arg)){
cache.put(arg, (Long)thisJoinPoint.proceed(thisJoinPoint.getArgs()));
}
return cache.get(arg);
}
}