Если я правильно понимаю, что вам нужно сделать (вместо того, чтобы выписывать первые n числа Фибоначчи), чтобы определить, является ли n числом Фибоначчи.
Таким образом, вы должны изменить свой метод, чтобы он продолжал генерировать последовательность Фибоначчи, пока не получите число> = n. Если оно равно, n - это число Фибоначчи, иначе нет.
Обновление: из-за неоднократных утверждений @ Moron о превосходстве алгоритма на основе формул по сравнению с простым, приведенным выше, я фактически провел сравнение производительности - конкретно между решением Якопо как алгоритм генератора и последняя версия StevenH как алгоритм, основанный на формуле . Для справки, вот точный код:
public static void main(String[] args) {
measureExecutionTimeForGeneratorAlgorithm(1);
measureExecutionTimeForFormulaAlgorithm(1);
measureExecutionTimeForGeneratorAlgorithm(10);
measureExecutionTimeForFormulaAlgorithm(10);
measureExecutionTimeForGeneratorAlgorithm(100);
measureExecutionTimeForFormulaAlgorithm(100);
measureExecutionTimeForGeneratorAlgorithm(1000);
measureExecutionTimeForFormulaAlgorithm(1000);
measureExecutionTimeForGeneratorAlgorithm(10000);
measureExecutionTimeForFormulaAlgorithm(10000);
measureExecutionTimeForGeneratorAlgorithm(100000);
measureExecutionTimeForFormulaAlgorithm(100000);
measureExecutionTimeForGeneratorAlgorithm(1000000);
measureExecutionTimeForFormulaAlgorithm(1000000);
measureExecutionTimeForGeneratorAlgorithm(10000000);
measureExecutionTimeForFormulaAlgorithm(10000000);
measureExecutionTimeForGeneratorAlgorithm(100000000);
measureExecutionTimeForFormulaAlgorithm(100000000);
measureExecutionTimeForGeneratorAlgorithm(1000000000);
measureExecutionTimeForFormulaAlgorithm(1000000000);
measureExecutionTimeForGeneratorAlgorithm(2000000000);
measureExecutionTimeForFormulaAlgorithm(2000000000);
}
static void measureExecutionTimeForGeneratorAlgorithm(int x) {
final int count = 1000000;
final long start = System.nanoTime();
for (int i = 0; i < count; i++) {
isFibByGeneration(x);
}
final double elapsedTimeInSec = (System.nanoTime() - start) * 1.0e-9;
System.out.println("Running generator algorithm " + count + " times for " + x + " took " +elapsedTimeInSec + " seconds");
}
static void measureExecutionTimeForFormulaAlgorithm(int x) {
final int count = 1000000;
final long start = System.nanoTime();
for (int i = 0; i < count; i++) {
isFibByFormula(x);
}
final double elapsedTimeInSec = (System.nanoTime() - start) * 1.0e-9;
System.out.println("Running formula algorithm " + count + " times for " + x + " took " +elapsedTimeInSec + " seconds");
}
static boolean isFibByGeneration(int x) {
int a=0;
int b=1;
int f=1;
while (b < x){
f = a + b;
a = b;
b = f;
}
return x == f;
}
private static boolean isFibByFormula(int num) {
double first = 5 * Math.pow((num), 2) + 4;
double second = 5 * Math.pow((num), 2) - 4;
return isWholeNumber(Math.sqrt(first)) || isWholeNumber(Math.sqrt(second));
}
private static boolean isWholeNumber(double num) {
return num - Math.round(num) == 0;
}
Результаты удивили даже меня:
Running generator algorithm 1000000 times for 1 took 0.007173537000000001 seconds
Running formula algorithm 1000000 times for 1 took 0.223365539 seconds
Running generator algorithm 1000000 times for 10 took 0.017330694 seconds
Running formula algorithm 1000000 times for 10 took 0.279445852 seconds
Running generator algorithm 1000000 times for 100 took 0.030283179 seconds
Running formula algorithm 1000000 times for 100 took 0.27773557800000004 seconds
Running generator algorithm 1000000 times for 1000 took 0.041044322 seconds
Running formula algorithm 1000000 times for 1000 took 0.277931134 seconds
Running generator algorithm 1000000 times for 10000 took 0.051103143000000004 seconds
Running formula algorithm 1000000 times for 10000 took 0.276980175 seconds
Running generator algorithm 1000000 times for 100000 took 0.062019335 seconds
Running formula algorithm 1000000 times for 100000 took 0.276227007 seconds
Running generator algorithm 1000000 times for 1000000 took 0.07422898800000001 seconds
Running formula algorithm 1000000 times for 1000000 took 0.275485013 seconds
Running generator algorithm 1000000 times for 10000000 took 0.085803922 seconds
Running formula algorithm 1000000 times for 10000000 took 0.27701090500000003 seconds
Running generator algorithm 1000000 times for 100000000 took 0.09543419600000001 seconds
Running formula algorithm 1000000 times for 100000000 took 0.274908403 seconds
Running generator algorithm 1000000 times for 1000000000 took 0.10683704200000001 seconds
Running formula algorithm 1000000 times for 1000000000 took 0.27524084800000004 seconds
Running generator algorithm 1000000 times for 2000000000 took 0.13019867100000002 seconds
Running formula algorithm 1000000 times for 2000000000 took 0.274846384 seconds
Короче говоря, алгоритм алгоритма генератора превосходит решение на основе формул по всем положительным значениям int - даже близко к максимальному значению int он более чем в два раза быстрее!
Вот вам и оптимизация производительности на основе убеждений; -)
Для записи, модифицируя приведенный выше код для использования long
переменных вместо int
, алгоритм генератора становится медленнее (как и следовало ожидать, так как теперь он должен сложить long
значений), и точка переключения, где Формула начинает работать быстрее около 1000000000000L, то есть 10 12 .
Update2: Как отмечали IVlad и Moron, я не совсем эксперт в вычислениях с плавающей запятой :-), основываясь на их предложениях, я улучшил формулу до этого:
private static boolean isFibByFormula(long num)
{
double power = (double)num * (double)num;
double first = 5 * power + 4;
double second = 5 * power - 4;
return isWholeNumber(Math.sqrt(first)) || isWholeNumber(Math.sqrt(second));
}
Это снизило точку переключения до прибл. 10 8 (для версии long
- генератор с int
все еще быстрее для всех значений типа int). Нет сомнений в том, что замена вызовов sqrt
чем-то вроде предложенного @Moron еще больше подтолкнет точку переключения.
Моя (и IVlad) точка зрения заключалась в том, что всегда будет точка переключения, ниже которой алгоритм генератора работает быстрее. Так что утверждения о том, какой из них работает лучше, не имеют смысла вообще, только в контексте.