Определение того, является ли число числом Фибоначчи

Мне нужно написать код Java, который проверяет, находится ли введенное пользователем число в последовательности Фибоначчи.

У меня нет проблем с записью последовательности Фибоначчи для вывода, но (вероятно, потому что уже поздно) я изо всех сил пытаюсь придумать последовательность, «является ли это числом Фибоначчи». Я начинаю снова и снова. Это действительно разбивает мне голову.

Сейчас у меня n-е.

public static void main(String[] args)
{
    ConsoleReader console = new ConsoleReader();

    System.out.println("Enter the value for your n: ");
    int num = (console.readInt());
    System.out.println("\nThe largest nth fibonacci: "+fib(num));
    System.out.println();
}

static int fib(int n){
    int f = 0;
    int g = 1;
    int largeNum = -1;
    for(int i = 0; i < n; i++)
    {
      if(i == (n-1))
          largeNum = f;
      System.out.print(f + " ");
      f = f + g;
      g = f - g;
    }
    return largeNum;
}

person Emily    schedule 29.06.2010    source источник


Ответы (13)


Прочтите раздел под названием «распознавание чисел Фибоначчи» в википедии.

В качестве альтернативы положительное целое число z является числом Фибоначчи тогда и только тогда, когда одно из 5z ^ 2 + 4 или 5z ^ 2-4 является полным квадратом. [17]

В качестве альтернативы вы можете продолжать генерировать числа Фибоначчи до тех пор, пока одно из них не станет равным вашему числу: если это так, то ваше число является числом Фибоначчи, если нет, числа в конечном итоге станут больше, чем ваше число, и вы можете остановиться. Однако это довольно неэффективно.

person IVlad    schedule 29.06.2010
comment
Просто любопытно, насколько большим должно быть это число, чтобы оно стало более неэффективным, чем операция извлечения квадратного корня? - person Chris J; 29.06.2010
comment
@Chris J - хороший вопрос. Генерация первых n чисел Фибоначчи - это O(n) временная операция. Извлечение квадратного корня из z равно O(log z). Я склонен сказать, что для n, достаточно большого, чтобы числа Фибоначчи требовали больших целых чисел, квадратный корень быстрее, но я не уверен. - person IVlad; 29.06.2010
comment
последующие значения в последовательности Фибоначчи приближаются к очень специфическому соотношению (Золотому). следовательно, они могут быть приблизительно аппроксимированы как это отношение - количество шагов, необходимых для достижения этого числа (с некоторыми постоянными множителями). т.е. log (z) ~ n log (phi) - это означает, что извлечение квадратного корня и простой подсчет довольно близки. Тем не менее, я думаю, что преимущество может заключаться в том, что можно оценить нецелочисленность квадратного корня (это махает рукой, не совсем уверенно) меньше, чем log (z). - person Carl; 01.07.2010
comment
Святая корова хороший ответ! Как математик я удивлен, что это могло быть правдой. Потрясающе-о. - person Eric Lindauer; 08.10.2011

Если я правильно понимаю, что вам нужно сделать (вместо того, чтобы записывать первые 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.

Обновление2: Как отметили 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) точка зрения заключалась просто в том, что всегда будет точка переключения, ниже которой алгоритм генератора работает быстрее. Таким образом, утверждения о том, какой из них работает лучше, не имеют значения в целом, только в контексте.

person Péter Török    schedule 29.06.2010
comment
Похоже, что все, за кого проголосовали, и это не означало, что предложение IVlad было отвергнуто одним. Выводы делайте сами. - person David M; 29.06.2010
comment
Чтобы прояснить ситуацию, я не голосовал против. Я даже не уверен на 100%, что мое решение действительно более эффективно. Я собираюсь проголосовать за ваши ответы и ответы @David M, потому что они на самом деле могут быть лучше. - person IVlad; 29.06.2010
comment
Извиняюсь за инсинуацию IVlad. Некоторые из нас были отвергнуты без объяснения причин - не могла бы ответственная сторона дать нам какие-либо отзывы? - person David M; 29.06.2010
comment
Это очень честно с вашей стороны, @IVlad, спасибо за отзыв. Видимо у вас (или @Soufiane) есть секретный фанат :-) - person Péter Török; 29.06.2010
comment
-1: Нет необходимости в каких-либо фанатских компаниях, чтобы проголосовать против этого ответа. ИМО, это довольно плохой ответ. Если вы хотите сгенерировать числа Фибоначчи и проверить ›= n, выполните хотя бы двоичный поиск! Совершенно наивно просто генерировать последовательность, пока вы не дойдете до числа ›= n. Я почти уверен, что этот ответ совершенно бесполезен для OP. Ситуация усугубляется заявлением: «Вам нужно генерировать .... Вам это не нужно». Вы могли бы, но не должны. - person ; 01.07.2010
comment
... и прежде чем вы спросите, да, вы можете сгенерировать k-е число Фибоначчи без необходимости генерировать все предыдущие, что делает возможным двоичный поиск. Кроме того, иногда проводится голосование против, чтобы получить хорошие ответы наверху. Иногда это означает отклонение всех ответов, кроме одного. - person ; 01.07.2010
comment
@Moron, это наивный, но рабочий подход. Помните, что это домашнее задание, а не производственная система, критичная к производительности :-) И она может даже быть оптимальной, в зависимости от контекста (см. Комментарий @IVlad выше) - вы действительно проводили какие-либо измерения производительности, чтобы увидеть при каких обстоятельствах формула, показанная в ответе Ивлада, превосходит генерацию последовательности? Если нет, о чем мы говорим? - person Péter Török; 01.07.2010
comment
@Moron, еще два момента по этому поводу: иногда проводится голосование против, чтобы получить хорошие ответы наверху. Иногда это означает отклонение всех ответов, кроме одного. 1) это звучит подозрительно близко к тактическое голосование против 2) это смехотворное объяснение того, что голосование против одного ответа имеет 1 балл, когда у верхнего ответа 12 ;-) Конечно, не стесняйтесь голосовать против, я не Не обращайте внимания на потерянные очки. То, что я делаю, - это шаткие рассуждения. - person Péter Török; 01.07.2010
comment
@Peter: Это совсем не тактическое голосование против. Часто люди голосуют за правильно выглядящие, но совершенно неправильные ответы, в то время как действительно правильные ответы просто томятся внизу. Смысл голосования против - получить качественные ответы наверху (поиск по мета, если вы не уверены). Голосование против при оставлении комментария позволяет людям узнать, что в ответе есть недостатки. Что касается опускания этого ответа, это было сделано для того, чтобы поставить точку. Это плохой ответ, и приведенные выше комментарии заставляют вас думать, что это не так. Откровенно говоря, то, что является шатким рассуждением, подразумевает, что IVlad мог быть причастен к тактическому голосованию против. Алгоритм IVlad будет ... - person ; 01.07.2010
comment
... выбейте из вашего алгоритма все дерьмо. Чтобы понять это, нам не нужно ничего измерять. Я согласен с домашним заданием. Алгоритм IVlad может быть излишним, но было сказано, что это худший алгоритм, чем этот, и меня не волнует, считаете ли вы, что вещи нужно измерять, чтобы это выяснить. Если вы не уверены, я ничем не могу вам помочь. - person ; 01.07.2010
comment
@Moron, Смысл голосования против - это получение качественных ответов наверху - ИМО, это суть голосования за. И если вы думаете, что я имел в виду, что IVlad был против, читайте внимательнее. - person Péter Török; 01.07.2010
comment
@Moron, как я уже сказал, не стесняйтесь думать, что мой ответ плохой - это ваше право, даже если мы не согласны. Суть вопроса выше заключалась в проблемах с реализацией конкретного алгоритма ОП. В моем ответе была указана основная причина и объяснено решение с точки зрения используемого в настоящее время алгоритма. Так что я все еще утверждаю, что это полезный ответ. - person Péter Török; 01.07.2010
comment
@Peter: Я не имел в виду, что вы намекали, что IVlad был противником, я просто назвал это шатким рассуждением :-). Конечно, голосование помогает получить качественные ответы, это очевидно! Какова ваша позиция? Я имел в виду, что бывают ситуации, когда за неправильные ответы тоже проголосуют, а хорошие ответы уйдут в небытие. В этом случае поможет голосование против и оставление комментария. Предлагаю внимательно прочитать то, что я написал :-). Кстати, если вы измените формулировку с «Вам нужно на ...» на «Вы могли ...», я буду рад снять свой голос против. В любом случае, прошу прощения, если я причинил вам беспокойство, я только подчеркивал важность. - person ; 01.07.2010
comment
@Peter: кстати, насчет последствий голосования против, ты действительно имел в виду, что голосование против происходило, но не обязательно со стороны IVlad. И это слишком затянулось. Прошу прощения за шум и неудобства. Я перестану вас беспокоить :-) - person ; 01.07.2010
comment
@Moron, см. Мое обновление по вопросу производительности. В остальном все нормально, без обид :-) - person Péter Török; 01.07.2010
comment
@Peter: Не используйте Math.Sqrt или Math.Pow! :-) Используйте двоичный поиск, чтобы определить, является ли 5f ^ 2 + - 4 точным квадратом. Или еще лучше используйте это: stackoverflow.com/questions/295579/ - person ; 01.07.2010
comment
@ Péter Török - без обид, но использовать Math.pow для возведения числа в квадрат - явно несправедливо и в целом плохая идея :). Кроме того, как сказал @Moron, sqrt также можно избежать, но мне было бы любопытно, каковы будут результаты, если вы просто избавитесь от pow. - person IVlad; 01.07.2010
comment
С кодом тестирования результат -1, который я дал, теперь вполне заслужен! Вы не можете просто поместить туда какую-либо реализацию и заявить, что одна лучше другой. Это становится глупо. - person ; 01.07.2010
comment
@IVlad, смотри мое обновление. @Moron, по крайней мере, я пытался опираться на факты, а не на догадки. Измерения и эксперименты можно улучшить, вера - нет. - person Péter Török; 01.07.2010
comment
@Peter: Вам не нужны два вызова sqrts. Кроме того, существует не более 40 чисел Фибоначчи ниже 10 ^ 8. Поместите их в таблицу поиска, и наивный метод может быть побежден и для небольших значений. Кроме того, я опубликовал некоторые результаты тестов, которые показывают, что порог на моей машине равен 50 (я полагаю, у меня есть FPU). Кстати, утверждать, что все нужно измерить, просто глупо. Как насчет того, чтобы измерить быструю сортировку и богосорт / пузырьковую сортировку? Может быть, вы сможете найти точку отсечения и сообщить нам, а может быть, разрушите наши убеждения? ;-) - person ; 02.07.2010
comment
@Moron, хорошее замечание о sqrt. Табличный поиск - действительно очень хорошее решение ... но позвольте мне отметить, что это новый, третий алгоритм. Что касается быстрой сортировки, как все узнают, что она (в целом) быстрее пузырьковой сортировки? Может быть, потому что кто-то где-то уже явно доказал это (путем измерения и / или математического доказательства)? :-) Ваши тесты на самом деле очень ясно показывают, зачем нужны измерения - устранение одного вызова sqrt не объясняет всей разницы в результатах. Даже один и тот же алгоритм может по-разному работать на разных платформах. - person Péter Török; 02.07.2010
comment
Скорее всего, у вас есть математическое доказательство в сочетании с эмпирическим свидетельством. Эти эмпирические данные, вероятно, бесполезны для сегодняшних машин, в то время как доказательства верны. Измерения всегда конечны и могут доходить только до определенного предела (изменение системы и т. Д.), Зависят от реализации / базовой машины и т. Д. И никогда не могут считаться доказательством. Все, что они доказывают, - это то, что для этого набора данных на этой машине в данный момент алгоритм A лучше, чем алгоритм B. Без сомнения, они важны, но они всего лишь инструмент. Не всегда нужно измерять, чтобы сравнивать. - person ; 02.07.2010
comment
Конечно, вы меняете машину, и все может измениться. Например, если бы у меня была машина, на которой вызов перехода был очень дорогим, ваш метод, вероятно, будет сканировать. Дело в том, что мы должны согласовать общую модель, прежде чем даже говорить о сравнении. Когда мы не говорим об этом, я полагаю, что разумно предположить, что какой-то достаточно распространенный процессор, такой как современные процессоры Intel, и в этом случае, ИМО, мы можем в значительной степени доказать, что метод sqrt превосходит наивный метод, начиная с достаточно малых n . - person ; 02.07.2010
comment
кстати, я только что заметил, что вы изменили формулировку. Я удалил -1. - person ; 02.07.2010
comment
@Moron, я понимаю вашу точку зрения, теперь, когда вы действительно ее объяснили ;-) И - сюрприз, сюрприз - в основном согласен с этим ... с одним замечанием: для сравнения вам нужно определить конкретные критерии. Один из возможных критериев: чем меньше большой O, тем лучше - он будет вашим, если я не ошибаюсь. Другой - ближе к оригинальному подходу OP, тем лучше - это был мой. Очевидно, что в данном случае они противоречат друг другу (а их может быть любое количество больше) ... так что алгоритм A может быть лучше алгоритма B только по определенным критериям, а не в целом. - person Péter Török; 02.07.2010
comment
@Moron, я вижу, вы добавили очень похожий комментарий, а я добавил свой ... да, эти неявные предположения беспокоили меня с самого начала нашего разговора. Теперь, когда вы сделали их явными, мы наконец можем согласиться :-) - person Péter Török; 02.07.2010
comment
буду читать этот комментарий со вкусом. Кажется, что все хотят объяснения, когда голосуют против без причины, но мало кто из них предлагает способ сделать это лучше; Я бы пошел на принудительное комментирование голосов против, но это вызывает резкую оппозицию на metaSO. +1 за свои старания и с момента: как люди могут считать этот ответ бесполезным? - person ShinTakezou; 03.07.2010
comment
(читайте; даже в исходном состоянии и скользкой формулировке, я думаю, что OP может счесть это полезным, поэтому удаленный -1, к счастью, был удален, но все еще есть бессмысленный -1. ба) - person ShinTakezou; 03.07.2010

Вместо передачи индекса n напишите функцию, которая принимает ограничение и заставляет ее генерировать числа Фибоначчи до этого ограничения включительно. Получите, чтобы он возвращал логическое значение в зависимости от того, достигает ли он или пропускает предел, и вы можете использовать это, чтобы проверить, входит ли это значение в последовательность.

Поскольку это домашнее задание, такой толчок, вероятно, все, что мы должны вам дать ...

person David M    schedule 29.06.2010

В порядке. Поскольку люди утверждали, что я просто говорю «факты» против «предположений») без каких-либо данных, подтверждающих это, я написал собственный тест.

Не java, а код C # ниже.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SO
{
    class Program
    {
        static void Main(string[] args)
        {
            AssertIsFibSqrt(100000000);

            MeasureSequential(1);
            MeasureSqrt(1);

            MeasureSequential(10);
            MeasureSqrt(10);

            MeasureSequential(50);
            MeasureSqrt(50);

            MeasureSequential(100);
            MeasureSqrt(100);


            MeasureSequential(100000);
            MeasureSqrt(100000);

            MeasureSequential(100000000);
            MeasureSqrt(100000000);

        }

        static void MeasureSequential(long n)
        {
            int count = 1000000;
            DateTime start = DateTime.Now;
            for (int i = 0; i < count; i++)
            {
                IsFibSequential(n);
            }
            DateTime end = DateTime.Now;

            TimeSpan duration = end - start;

            Console.WriteLine("Sequential for input = " + n + 
                              " : " + duration.Ticks);
        }

        static void MeasureSqrt(long n)
        {
            int count = 1000000;

            DateTime start = DateTime.Now;
            for (int i = 0; i < count; i++)
            {
                IsFibSqrt(n);
            }
            DateTime end = DateTime.Now;

            TimeSpan duration = end - start;

            Console.WriteLine("Sqrt for input =  " + n + 
                              " : " + duration.Ticks);
        }

        static void AssertIsFibSqrt(long x)
        {

            Dictionary<long, bool> fibs = new Dictionary<long, bool>();
            long a = 0;
            long b = 1;
            long f = 1;

            while (b < x)
            {
                f = a + b;
                a = b;
                b = f;

                fibs[a] = true;
                fibs[b] = true;
            }

            for (long i = 1; i <= x; i++)
            {
                bool isFib = fibs.ContainsKey(i);

                if (isFib && IsFibSqrt(i))
                {
                    continue;
                }

                if (!isFib && !IsFibSqrt(i))
                {
                    continue;
                }

                Console.WriteLine("Sqrt Fib test failed for: " + i);
            }
        }
        static bool IsFibSequential(long x)
        {
            long a = 0;
            long b = 1;
            long f = 1;

            while (b < x)
            {
                f = a + b;
                a = b;
                b = f;
            }
            return x == f;
        }

        static bool IsFibSqrt(long x)
        {
            long y = 5 * x * x + 4;

            double doubleS = Math.Sqrt(y);

            long s = (long)doubleS;

            long sqr = s*s;

            return (sqr == y || sqr == (y-8));
        }
    }
}

А вот и вывод

Sequential for input = 1 : 110011
Sqrt for input =  1 : 670067

Sequential for input = 10 : 560056
Sqrt for input =  10 : 540054

Sequential for input = 50 : 610061
Sqrt for input =  50 : 540054

Sequential for input = 100 : 730073
Sqrt for input =  100 : 540054

Sequential for input = 100000 : 1490149
Sqrt for input =  100000 : 540054

Sequential for input = 100000000 : 2180218
Sqrt for input =  100000000 : 540054

Метод sqrt превосходит наивный метод, когда сам n = 50, возможно, из-за наличия аппаратной поддержки на моей машине. Даже если бы оно было 10 ^ 8 (как в тесте Питера), под этим пороговым значением находится не более 40 чисел Фибоначчи, которые можно было бы легко поместить в таблицу поиска и при этом превзойти наивную версию для меньших значений.

Также у Питера плохая реализация SqrtVersion. На самом деле ему не нужно вычислять два квадратных корня или вычислять степени с помощью Math.Pow. Он мог бы хотя бы попытаться сделать это лучше, прежде чем опубликовать результаты своих тестов.

В любом случае, я позволю этим фактам говорить сами за себя, а не так называемым «догадкам».

person Community    schedule 01.07.2010
comment
Очень умное замечание об удивительно небольшом количестве чисел выдумки ниже порогового значения. Эта ветка горит! - person Eric Lindauer; 08.10.2011

Положительное целое число x является числом Фибоначчи тогда и только тогда, когда одно из 5x ^ 2 + 4 и 5x ^ 2-4 является полным квадратом.

person Soufiane Hassou    schedule 29.06.2010
comment
у вас есть ссылка на эту формулу? это вообще правильно? - person Chris J; 29.06.2010
comment
Распознавание чисел Фибоначчи: en.wikipedia.org/wiki/ - person holsee; 29.06.2010

Существует ряд методов, которые можно использовать, чтобы определить, входит ли данное число в последовательность Фибоначчи, выбор из которых можно увидеть на википедия.

Однако, учитывая то, что вы уже сделали, я бы, вероятно, использовал более грубый подход, например следующий:

  1. Сгенерируйте число Фибоначчи
  2. Если оно меньше целевого числа, сгенерируйте следующие фибоначчи и повторите
  3. Если это целевое число, то успех
  4. Если оно больше целевого числа, то неудача.

Я бы, вероятно, использовал рекурсивный метод, передав текущее n-значение (т.е. чтобы вычислить n-е число Фибоначчи) и целевое число.

person Edd    schedule 29.06.2010

Если моя Ява не слишком ржавая ...

static bool isFib(int x) {
    int a=0;
    int b=1;
    int f=1;
    while (b < x){
        f = a + b;
        a = b;
        b = f;
    }
    return x == f;
}
person Iacopo    schedule 29.06.2010

Пытаясь использовать уже написанный вами код, я бы сначала предложил следующее, так как это простейшее решение (но не самое эффективное):

private static void main(string[] args)
{
    //This will determnine which numbers between 1 & 100 are in the fibonacci series
    //you can swop in code to read from console rather than 'i' being used from the for loop
    for (int i = 0; i < 100; i++)
    {
        bool result = isFib(1);

        if (result)
            System.out.println(i + " is in the Fib series.");

        System.out.println(result);
    }

}

private static bool isFib(int num)
{
    int counter = 0;

    while (true)
    {
        if (fib(counter) < num)
        {
            counter++;
            continue;
        }

        if (fib(counter) == num)
        {
            return true;
        }

        if (fib(counter) > num)
        {
            return false;
        }
    }
}

Я бы предложил более элегантное решение при генерации чисел Фибоначчи, которое использует рекурсию следующим образом:

public static long fib(int n) 
{
   if (n <= 1) 
      return n;
   else 
      return fib(n-1) + fib(n-2);
}

Для получения дополнительной информации читайте: http://en.wikipedia.org/wiki/Fibonacci_number#Recognizing_Fibonacci_numbers

Вы увидите, что есть несколько более эффективных способов проверить, принадлежит ли число к серии Фибоначчи, а именно: (5z ^ 2 + 4 или 5z ^ 2-4) = полный квадрат.

//(5z^2 + 4 or 5z^2 − 4) = a perfect square 
//perfect square = an integer that is the square of an integer
private static bool isFib(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 bool isWholeNumber(double num)
{
    return num - Math.round(num) == 0;    
}
person holsee    schedule 29.06.2010
comment
Как показал Петер Торок в другом ответе на этот вопрос, проверка идеального квадрата проводится только для достаточно больших чисел (около 1000000000000 и более в его тестах). Конечно, для более низких значений это может стать быстрее, если вы замените проверку того, является ли число точным квадратом, чем-то более эффективным. - person Frerich Raabe; 01.07.2010
comment
@Frerich: Не обижайся на Питера, но его реализация проверки sqrt - отстой и практически бесполезна в тестировании. - person ; 01.07.2010
comment
@Moron, я не утверждаю, что это мое - он был скопирован прямо отсюда :-) - person Péter Török; 02.07.2010
comment
@ Питер: Понятно. Я прошу прощения :-) - person ; 02.07.2010

Я не знаю, существует ли фактическая формула, которую вы можете применить к пользовательскому вводу, однако вы можете сгенерировать последовательность Фибоначчи и сравнить ее с пользовательским вводом, пока она не станет меньше, чем последнее сгенерированное число.

int userInput = n;
int a = 1, b = 1;

while (a < n) {
  if (a == n)
    return true;

  int next = a + b;
  b = a;
  a = next;
}

return false;
person Chris J    schedule 29.06.2010

Вы можете сделать это двумя способами: рекурсивным и математическим. рекурсивный способ начать генерировать последовательность Фибоначчи, пока вы не нажмете число или не передадите его математическим способом, красиво описанным здесь ... http://www.physicsforums.com/showthread.php?t=252798

удачи.

person Stas    schedule 29.06.2010

Рассмотрим последовательность чисел Фибоначчи 1,1,2,3,5,8,13,21 и т. Д. Желательно построить 3 стека каждая емкостью 10, содержащих числа из приведенных выше последовательностей, следующим образом:

Стек 1: первые 10 чисел последовательности. Стек 2: первые 10 простых чисел из последовательности. Стек 3: первые 10 непростых чисел последовательности.

(i) Дайте алгоритм блок-схемы (ii) Напишите программу (на BASIC, C ++ или Java) для реализации этого.

Вывод: По мере того, как выполняются операции со стеком, вы должны отображать в любой удобной форме 3 стека вместе со значениями, хранящимися в них.

person Seidu Lukman Lutie    schedule 20.09.2013

Определение числа по шкале Фибоначчи по формуле:

public static boolean isNumberFromFibonacciSequence(int num){

    if (num == 0 || num == 1){
        return true;
    }

    else {
        //5n^2 - 4 OR 5n^2 + 4 should be perfect squares
        return isPerfectSquare( 5*num*num - 4) || isPerfectSquare(5*num*num - 4);
    }
}

private static boolean isPerfectSquare(int num){
        double sqrt = Math.sqrt(num);
        return sqrt * sqrt == num;
}
person realPK    schedule 28.07.2016

Думал, что это просто, пока мне не пришлось ломать голову над этим несколько минут. Это сильно отличается от генерации последовательности Фибоначчи. Эта функция возвращает 1, если это значение Фибоначи, или 0, если нет.

public static int isFibonacci (int n){
  int isFib = 0;
  int a = 0, b = 0, c = a + b; // set up the initial values
  do 
   {
    a = b;
    b = c;
    c = a + b;
    if (c == n)
    isFib = 1;
    } while (c<=n && isFin == 0)
  return isFib;
}

public static void main(String [] args){
  System.out.println(isFibonacci(89));
}
person karto    schedule 03.11.2017