Тест, если число Фибоначчи


Я знаю, как составить список чисел Фибоначчи, но я не знаю, как я могу проверить, принадлежит ли данное число к списку Фибоначчи - один из способов, который приходит в голову, - это создать список fib. числа до этого числа и посмотреть, если он принадлежит к массиву, но есть другой, более простой и быстрый способ.

какие идеи ?

20 69

20 ответов:

очень хороший тест, Что N является числом Фибоначчи тогда и только тогда 5 N^2 + 4 или 5N^2 – 4 - это квадрат числа. Для идей о том, как эффективно проверить, что число квадратных см. и объяснение.

надеюсь, что это помогает

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

посмотреть Баснословные Числа Фибоначчи дополнительные.

alt text

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

существует менее 80 чисел Фибоначчи, которые могут даже содержаться в стандартном 64-разрядном целочисленном значении.

вот мое решение, которое работает полностью меньше чем число, которое будет проверено.
(написано на C#, используя основные типы, такие как double и long. Но алгоритм должно работать нормально для больших типов.)

static bool IsFib(long T, out long idx)
{
    double root5 = Math.Sqrt(5);
    double phi = (1 + root5) / 2;

    idx    = (long)Math.Floor( Math.Log(T*root5) / Math.Log(phi) + 0.5 );
    long u = (long)Math.Floor( Math.Pow(phi, idx)/root5 + 0.5);

    return (u == T);
}


Более чем через 4 года после того, как я написал этот ответ, комментатор спросил о втором параметре, переданном out.

параметр #2-это "индекс" в последовательности Фибоначчи.
Если значение должно быть проверено,T - это число Фибоначчи, а затем idx будет 1-индекс этого числа в последовательности Фибоначчи. (за одним заметным исключением)

последовательность Фибоначчи 1 1 2 3 5 8 13, так далее.
3-это 4-е число в последовательности:IsFib(3, out idx); вернутся true и значение 4.
8-это 6-е число в последовательности: IsFib(8, out idx); вернутся true и значение 6.
13-это 7-е число;IsFib(13, out idx); вернутся true и значение 7.

единственное исключение IsFib(1, out idx);, что вернет 2, даже если значение 1 отображается как в индексе 1, так и в индексе 2.

если IsFib передается не число Фибоначчи, это вернется false и значение idx будет индекс самого большого числа Фибоначчи меньше чем T.

16 не является значением Фибоначчи.
IsFib(16, out idx); вернутся false и значение 7.
Вы можете использовать Формула Бине чтобы преобразовать индекс 7 в значение Фибоначчи 13, которое является самым большим числом меньше 16.

#!/bin/bash
victim="144"
curl http://aux.planetmath.org/files/objects/7680/fib.txt | sed 's/^[0-9]*//;s/[ \t]//g' | grep "^$victim$" >/dev/null 2>/dev/null
if [[ $? -eq 0 ]] ; then
    echo "$victim is a fibonacci number"
else
    echo "$victim aint"
fi

Если ваши числа имеют ограниченный размер, чем просто положить все числа Фибоначчи ниже верхней границы в хэш-таблицу и тестирование сдерживания будет делать трюк. Есть очень мало чисел Фибоначчи (например, только 38 ниже 5 млн), так как они растут экспоненциально.

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

положительное целое число ω является числом Фибоначчи

, если и только если одним из2 + 4 и 5ω2 - 4 является полным квадратом

С у (сказочные) числа Фибоначчи Альфреда Posamentier и Ингмар Леманн

bool isFibonacci(int  w)
{
       double X1 = 5 * Math.Pow(w, 2) + 4;
       double X2 = 5 * Math.Pow(w, 2) - 4;

       long X1_sqrt = (long)Math.Sqrt(X1);
       long X2_sqrt = (long)Math.Sqrt(X2);   

       return (X1_sqrt*X1_sqrt == X1) || (X2_sqrt*X2_sqrt == X2) ;
}

я скопировал его из этого источника


фрагмент, который печатает числа Фибоначчи между 1k и 10k.

for (int i = 1000; i < 10000; i++)
{
         if (isFibonacci(i))
              Console.Write(" "+i);
}

OMG есть только четыре!!!

С другим методом

from math import *

phi = 1.61803399
sqrt5 = sqrt(5)

def F(n):
    return int((phi**n - (1-phi)**n) /sqrt5)

def isFibonacci(z):
    return F(int(floor(log(sqrt5*z,phi)+0.5))) == z

print [i for i in range(1000,10000) if isFibonacci(i)]

к решению, взгляните на Формулу Бине.
(Ищите "выражение закрытой формы" под Число Фибоначчи в Википедии)

Он говорит, что последовательность чисел Фибоначчи создаются по простой формуле:

alt text

Я верю, если вы решите для n, и проверить, если n - Это целое число, вы будете иметь свой ответ.

Edit как указывает @psmears, та же статья в Википедии также есть раздел по обнаружению чисел Фибоначчи. Википедия является отличным источником.

смотрите раздел "распознавание чисел Фибоначчи" на статья Википедии о числах Фибоначчи.

Так как числа Фибоначчи растут экспоненциально, метод, который вы предлагаете, довольно быстрый. Другой - это этой.

из Википедии:http://en.wikipedia.org/wiki/Fibonacci_number

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

основываясь на более ранних ответах меня и psmears, я написал этот код C#.

Он идет через шаги медленно, и его можно ясно уменьшить и оптимизировать:

// Input: T: number to test.
// Output: idx: index of the number in the Fibonacci sequence.
//    eg: idx for 8 is 6. (0, 1, 1, 2, 3, 5, 8)
// Return value: True if Fibonacci, False otherwise.
static bool IsFib(long T, out int idx)
{
    double root5 = Math.Sqrt(5);
    double PSI = (1 + root5) / 2;

    // For reference, IsFib(72723460248141) should show it is the 68th Fibonacci number

    double a;

    a = T*root5;
    a = Math.Log(a) / Math.Log(PSI);
    a += 0.5;
    a = Math.Floor(a);
    idx = (Int32)a;

    long u = (long)Math.Floor(Math.Pow(PSI, a)/root5 + 0.5);

    if (u == T)
    {
        return true;
    }
    else
    {
        idx = 0;
        return false;
    }
}

тестирование показывает, что это работает для первых 69 чисел Фибоначчи, но ломается для 70-го.

F(69) = 117,669,030,460,994 - Works
F(70) = 190,392,490,709,135 - Fails

в целом, если вы не используете какую-то библиотеку BigInt, вероятно, лучше иметь простую таблицу поиска чисел Фибоначчи и проверить это, а не запускать алгоритм.

список первых 300 номеров легко доступен в интернете.

но этот код описывает работоспособный алгоритм, при условии, что у вас достаточно точности, и не переполняет вашу систему представления чисел.

re: код Ахмада-более простой подход без рекурсии или указателей, довольно наивный, но не требует почти никакой вычислительной мощности для чего-либо, кроме действительно титанических чисел (примерно 2n дополнений для проверки N-го числа fib, которое на современной машине займет миллисекунды в худшем случае)

/ / возвращает pos, если он что-то находит, 0, если это не так (C/C++ обрабатывает любое значение !=0 как истина, так же конечный результат)

int isFib (long n)
{
    int pos = 2;
    long last = 1;
    long current = 1;
    long temp;

    while (current < n)
    {
        temp = last;
        last = current;
        current = current + temp;
        pos++;
    }

    if (current == n)
        return pos;
    else
        return 0;

}

общее выражение для чисел Фибоначчи Ф(Н) = [ [(1+корень(5))/2] SUP и Н+1 - [(1-корень(5))/2] с SUP П+1 ]/ корень(5) ..... (*) Второе экспоненциально стремится к нулю при больших n и проведения численные операции получаем F (n) = [(1.618) sup n+1 ] / 2.236

Если K - это число для проверки log (k*2.2336) / log(1.618) должно быть целым числом!

пример для K равный 13 мой калькулятор дает ответ 7.00246 При k равном 14 ответ таков 7.1564.

вы можете увеличить уверенность в результате, взяв ближайшее целое число к ответьте и подставьте в ( * ), чтобы подтвердить, что результат K

насколько велики цифры, с которыми вы имеете дело?

может ли таблица поиска работать для вас? (предварительно вычисленный список чисел, которые вы можете найти в)

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

Я провел некоторые тесты по методам, представленным здесь, наряду с простым добавлением, предварительным вычислением массива и запоминанием результатов в хэше. Для Perl, по крайней мере, метод возведения в квадрат немного быстрее, чем логарифмический метод, возможно, на 20% быстрее. Как указывает абеленки, это компромисс между тем, есть ли у вас место для возведения в квадрат битовых чисел.

конечно, самый быстрый способ-это окрошка Все числа Фибоначчи в доменном пространстве. Вдоль линий другой момент, что абеленки делает, есть только 94 из этих присоски, которые меньше, чем 2^64.

вы должны просто предварительно вычислить их и поместить их в хэш Perl, словарь Python или что-то еще.

свойства чисел Фибоначчи очень интересны, но использование их для определения того, является ли какое-то целое число в компьютерной программе одним, похоже на написание подпрограммы для вычисления pi каждый раз, когда программа запускается.

Это мое решение, я не уверен, что это тесты. Надеюсь, это поможет!

def is_fibonacci?(i)
  a,b=0,1
    until b >= i
        a,b=b,a+b
        return true if b == i
    end
end

что a, b=b, a+b делает

 0, 1 = 1, 0 +1
 1, 1 = 1, 1 + 1
 1, 2 = 2, 1 + 2
 2, 3 = 3, 2 + 3

fib1 = fib2
fib2 = fib1 + fib2

версия Scala -

def isFib(n: Int): Boolean = {

def checkFib(f1: Int = 1, f2: Int = 1): Boolean = {

if(n == f1 || n == f2) true
else if(n < f2) false
else checkFib(f2, f1+f2)

}

checkFib()

}

Java-решение может быть сделано, как показано ниже. Но все же его можно оптимизировать

следующее решение работает для

  1. 1≤T≤10 ^5
  2. 1≤N≤10 ^10

T-нет.тестов , N-это числа

    import java.util.Scanner;
    import java.math.BigDecimal;
    import java.math.RoundingMode;

    public class FibonacciTester {
        private static BigDecimal zero = BigDecimal.valueOf(0);
        private static BigDecimal one = BigDecimal.valueOf(1);
        private static BigDecimal two = BigDecimal.valueOf(2);
        private static BigDecimal four = BigDecimal.valueOf(4);
        private static BigDecimal five = BigDecimal.valueOf(5);

        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int n = sc.nextInt();
            BigDecimal[] inputs = new BigDecimal[n];
            for (int i = 0; i < n; i++) {
                inputs[i] = sc.nextBigDecimal();
            }

            for (int i = 0; i < inputs.length; i++) {
                if (isFibonacci(inputs[i]))
                    System.out.println("IsFibo");
                else
                    System.out.println("IsNotFibo");
            }


        }

        public static boolean isFibonacci(BigDecimal num) {
            if (num.compareTo(zero) <= 0) {
                return false;
            }

            BigDecimal base = num.multiply(num).multiply(five);
            BigDecimal possibility1 = base.add(four);
            BigDecimal possibility2 = base.subtract(four);


            return (isPerfectSquare(possibility1) || isPerfectSquare(possibility2));
        }

        public static boolean isPerfectSquare(BigDecimal num) {
            BigDecimal squareRoot = one;
            BigDecimal square = one;
            BigDecimal i = one;
            BigDecimal newSquareRoot;
            int comparison = -1;

            while (comparison != 0) {
                if (comparison < 0) {
                    i = i.multiply(two);
                    newSquareRoot = squareRoot.add(i).setScale(0, RoundingMode.HALF_UP);
                } else {
                    i = i.divide(two);
                    newSquareRoot = squareRoot.subtract(i).setScale(0, RoundingMode.HALF_UP);
                }

                if (newSquareRoot.compareTo(squareRoot) == 0) {
                    return false;
                }

                squareRoot = newSquareRoot;
                square = squareRoot.multiply(squareRoot);
                comparison = square.compareTo(num);
            }

            return true;
        }
    }
int isfib(int n /* number */, int &pos /* position */)
{
   if (n == 1)
   {
      pos=2;  // 1 1
      return 1;
   }
   else if (n == 2)
   {
      pos=3;  // 1 1 2
      return 1;
   }
   else
   {
      int m = n /2;
      int p, q, x, y;
      int t1=0, t2 =0;
      for (int i = m; i < n; i++)
      {
        p = i;
        q = n -p;    // p + q = n
        t1 = isfib(p, x);
        if (t1) t2 = isfib(q, y);
        if (t1 && t2 && x == y +1)
        {
           pos = x+1;
           return 1; //true
        }
      }
      pos = -1;
      return 0; //false
   }
}

Как насчет этого?

#include <stdio.h>
#include <math.h>

int main()
{
int number_entered, x, y;

printf("Please enter a number.\n");
scanf("%d", &number_entered);
x = y = 5 * number_entered^2 + 4;        /*Test if 5N^2 + 4 is a square number.*/
x = sqrt(x);
x = x^2;
if (x == y)
{
        printf("That number is in the Fibonacci sequence.\n");
    }
x = y = 5 * number_entered^2 - 4;        /*Test if 5N^2 - 4 is a square number.*/
x = sqrt(x);
x = x^2;
if (x == y)
{
    printf("That number is in the Fibonacci sequence.\n");
}
else
{
    printf("That number isn't in the Fibonacci sequence.\n");
}
return 0;
}

будет ли это работать?