Javanacci — пълен код
Всеки клас в собствен файл. Пакет: bg.tu_varna.javanacci.
InvalidFibonacciPositionException.java — checked exception за отрицателна позиция
package bg.tu_varna.javanacci;
class InvalidFibonacciPositionException extends Exception { private final long invalidPosition;
public InvalidFibonacciPositionException(long position) { super("Позиция " + position + " е отрицателна; допустими стойности: [0, " + Long.MAX_VALUE + "]"); this.invalidPosition = position; }
public long getInvalidPosition() { return invalidPosition; }}FibonacciRunnable.java — параметризиран интерфейс с метод run()
package bg.tu_varna.javanacci;
interface FibonacciRunnable<R> { R run();}AbstractFibonacciMachine.java — абстрактна база с Comparable по позиция
package bg.tu_varna.javanacci;
import java.math.BigInteger;
abstract class AbstractFibonacciMachine implements Comparable<AbstractFibonacciMachine> { protected final long position;
protected AbstractFibonacciMachine(long position) { this.position = position; }
public long getPosition() { return position; }
public abstract BigInteger run();
@Override public int compareTo(AbstractFibonacciMachine other) { return Long.compare(this.position, other.position); }}FibonacciMachine.java — конкретна машина; глобален кеш, обхождане напред, AutoCloseable
package bg.tu_varna.javanacci;
import java.math.BigInteger;import java.util.*;import static java.math.BigInteger.ZERO;import static java.math.BigInteger.ONE;
class FibonacciMachine extends AbstractFibonacciMachine implements FibonacciRunnable<BigInteger>, AutoCloseable {
public static final long MAX_POSITION = Long.MAX_VALUE;
// Sorted map — enables floorKey(n) to find the highest cached position ≤ n private static final NavigableMap<Long, BigInteger> CACHE = new TreeMap<>();
static { CACHE.put(0L, ZERO); CACHE.put(1L, ONE); }
public FibonacciMachine(long position) throws InvalidFibonacciPositionException { super(position); if (position < 0) { throw new InvalidFibonacciPositionException(position); } }
@Override public BigInteger run() { if (CACHE.containsKey(position)) { return CACHE.get(position); }
// Find highest cached position ≤ target, then iterate forward from there Long startPos = CACHE.floorKey(position); BigInteger prev = CACHE.get(startPos - 1); BigInteger curr = CACHE.get(startPos);
for (long i = startPos + 1; i <= position; i++) { BigInteger next = prev.add(curr); CACHE.put(i, next); prev = curr; curr = next; }
return CACHE.get(position); }
@Override public void close() { System.out.println("FibonacciMachine[" + position + "] приключи."); }
@Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof FibonacciMachine)) { return false; } return this.position == ((FibonacciMachine) obj).position; }
@Override public int hashCode() { return Long.hashCode(position); }
@Override public String toString() { return "FibonacciMachine[" + position + "]"; }}Javanacci.java — оркестратор; приема масив от позиции или брой за произволни; имплементира Iterable
package bg.tu_varna.javanacci;
import java.math.BigInteger;import java.util.*;
public class Javanacci implements Iterable<Javanacci.Result> {
public static class Result { private final long position; private final BigInteger value;
Result(long position, BigInteger value) { this.position = position; this.value = value; }
public long getPosition() { return position; } public BigInteger getValue() { return value; }
@Override public String toString() { return "fib(" + position + ") = " + value; } }
private final List<FibonacciMachine> machines;
public Javanacci(long[] positions) throws InvalidFibonacciPositionException { machines = new ArrayList<>(); for (long pos : positions) { machines.add(new FibonacciMachine(pos)); } }
public Javanacci(int count) throws InvalidFibonacciPositionException { machines = new ArrayList<>(); Random rng = new Random(); for (int i = 0; i < count; i++) { machines.add(new FibonacciMachine((long) (rng.nextDouble() * 100))); } }
public List<Result> runAll() { List<Result> results = new ArrayList<>(); Iterator<FibonacciMachine> it = machines.iterator(); while (it.hasNext()) { FibonacciMachine machine = it.next(); results.add(new Result(machine.getPosition(), machine.run())); } Collections.sort(results, Comparator.comparingLong(Result::getPosition)); return results; }
public static BigInteger runSingle(long position) throws InvalidFibonacciPositionException { try (FibonacciMachine machine = new FibonacciMachine(position)) { return machine.run(); } }
@Override public Iterator<Result> iterator() { return runAll().iterator(); }}JavanacciDemo.java — входна точка; три сценария на употреба
package bg.tu_varna.javanacci;
import java.math.BigInteger;
class JavanacciDemo { public static void main(String[] args) {
// 1. Explicit positions try { Javanacci jv = new Javanacci(new long[]{0, 1, 5, 10, 20, 50}); for (Javanacci.Result r : jv) { System.out.println(r); } } catch (InvalidFibonacciPositionException | IllegalArgumentException e) { System.err.println("Грешка: " + e.getMessage()); }
// 2. Random positions try { Javanacci jv = new Javanacci(5); for (Javanacci.Result r : jv) { System.out.println(r); } } catch (InvalidFibonacciPositionException e) { System.err.println("Грешка: " + e.getMessage()); }
// 3. Single position via try-with-resources try { System.out.println("fib(100) = " + Javanacci.runSingle(100)); } catch (InvalidFibonacciPositionException e) { System.err.println("Невалидна позиция: " + e.getInvalidPosition()); } }}