Determining whether a number is a Fibonacci number

前端 未结 14 1212
暗喜
暗喜 2021-01-18 05:35

I need to to write a Java code that checks whether the user inputed number is in the Fibonacci sequence.

I have no issue writing the Fibonacci sequence to output, b

14条回答
  •  孤城傲影
    2021-01-18 06:23

    Ok. Since people claimed I am just talking thin air ('facts' vs 'guesses') without any data to back it up, I wrote a benchmark of my own.

    Not java, but C# code below.

    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 fibs = new Dictionary();
                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));
            }
        }
    }
    

    And here is the output

    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
    

    The sqrt method beats the naive method when n=50 itself, perhaps due to the presence of hardware support on my machine. Even if it was 10^8 (like in Peter's test), there are at most 40 fibonacci numbers under that cutoff, which could easily be put in a lookup table and still beat the naive version for the smaller values.

    Also, Peter has a bad implementation of the SqrtVersion. He doesn't really need to compute two square roots or compute powers using Math.Pow. He could have atleast tried to make that better before publishing his benchmark results.

    Anyway, I will let these facts speak for themselves, instead of the so called 'guesses'.

提交回复
热议问题