Finding the closest fibonacci numbers

前端 未结 11 2150

I am trying to solve a bigger problem, and I think that an important part of the program is spent on inefficient computations.

I need to compute for a given number N, th

相关标签:
11条回答
  • 2021-02-02 14:10

    Since you consider only 64 bit integers, there are at most about 100 Fibonacci numbers to consider. You can precompute them using their definition Fn = Fn-1 + Fn-2.

    Then precompute another table that maps the number of leading zero bits to an index in the table of Fibonacci numbers, to the first number with that many leading zero bits.

    Now to find the interval use the number of leading zero bits of your number (this can be computed quickly as many processors have a special instruction for it) to find a starting point using the second table, and linearly search through the first table for the interval. Since there are at most two Fibonacci numbers between adjacent powers of two this takes at most 2 steps.

    This has the advantage that it only uses integer arithmetic, which is exact and tends to be faster than floating point computations.

    0 讨论(0)
  • 2021-02-02 14:15

    I just did a CodeChef puzzle that was this exact problem (http://www.codechef.com/problems/DPC204). I simply calculated the Fibonacci sequence from 0 to the end of the range, and counted how many were after the beginning of the range. My test for whatever their sample inputs were took 2.6M, and 0.00s, so the nieve solution is plenty fast enough.

    Basically, I made a big-unsigned-int class made of unsigned int[333], and calculate two numbers per loop, to avoid swaps.

    start with A=0,B=1;
    A+=B;B+=A; 
    now A==1,B==2, the next two Fib. numbers, with no swaps.
    A+=B;B+=A; 
    now A==3,B==5, the next two Fib. numbers, with no swaps.
    

    It is slightly complicated by the fact you have to stop and check if the neither, one, or both numbers are in the range, but A

    My solution on CodeChef clocked in at 0.00 seconds, so I think this method ought to be fast enough, you just have to write a function that adds one uint[333] to another uint[333] (using all 32 bits, just chars for each decimal digit)

    0 讨论(0)
  • 2021-02-02 14:21

    A number is Fibonacci if and only if one or both of (5*n^2 + 4) or (5*n^2 – 4) is a perfect square. I am using this premise to verify if the input number belongs to a fibonacci series or not.

    #include <stdio.h>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #include <stdlib.h>
    
    typedef struct node{
    
        int64_t value;
        struct node *next;
    
    }Node;
    
    Node *head ;
    
    void readElements(int);
    int isPerfectSquare(int64_t sqrValue);
    
    int main(){
    
        int input_count , flag=0;
        Node *temp_node = NULL;
        int64_t sqrValue = 0;
    
        scanf("%d" , &input_count);
    
        if((input_count < 1 )||(input_count > 100000)){
            printf("Total number of Inputs out of Range ..!!\n");
            return 1;
        }
    
        readElements(input_count);
    
        /*Reading the elements from the list*/
    
        temp_node = head;
    
        while(temp_node != NULL){
    
            sqrValue = 5*pow(temp_node->value , 2);
            flag = (isPerfectSquare(sqrValue+4) || isPerfectSquare(sqrValue-4));
    
            if(flag == 1){
                printf("IsFibo\n");
            }
            else{
                printf("IsNotFibo\n");
            }
    
            temp_node = temp_node->next;
    
        }   
    
    
    
        return 0;
    
    }
    
    
    void readElements(int input_count){
    
        int temp = 0;
        int64_t val = 0;
        Node *temp_node =NULL , *cur = NULL;
        char b[20];
    
    
        while (temp < input_count) {
    
            scanf("%s" , b);
            val = atol(b);
    
            if(val < 0 || val >10000000000)
                continue;
    
            temp_node = (Node*) malloc(sizeof(Node));
    
            temp_node->value = val;
            temp_node->next = NULL;
    
            if(head == NULL){
                head = cur = temp_node;
            }
            else{
                cur->next = temp_node;
                cur = temp_node;
            }
    
            temp++;
    
        }
    
    }
    
    int isPerfectSquare(int64_t sqrValue){
    
        int64_t s = 0;
    
        s = sqrt(sqrValue);
    
        return(s*s == sqrValue);
    
    }
    
    0 讨论(0)
  • 2021-02-02 14:23

    I think that an important part of the program is spent on inefficient computations.

    Have you profiled your code? As a general principle don't prematurely optimize; measure what parts are slowing it down. That way when you try optimizing, you can tell if the optimizations helped or hurt (often a sounds-good optimization will make it run worse; as say the compiler will not be able to do its optimizations or you aren't able to use your cpu's registers/cache as optimally).

    If this is what's slowing you down, I would do similar to Peng's great solution but pre-computing all the Fib numbers up to your largest value and store them into an array indexed by the corresponding expoential (n) from the closed-form (phi^**n - (1-phi)**n)/sqrt(5). His method will miscompute Fib numbers for large n with floating point arithmetic; unless you use arbitrary high-precision (which is slow). So your starting array is fib_array = [0,1,1,2,3,5,8,13,... ]. Then neglecting the small (1-phi)**n term, invert fib to find n (e.g., Peng's fib_inv), and take fib_array[n] as your first bound. If this bound is smaller (larger) than your value; you've found the lower (upper) bound, and so the other bound should be fib_array[n+1] (fib_array[n-1]).
    Or if you want to compute it use something from given a N that is better than Binet's formula. http://en.literateprograms.org/Fibonacci_numbers_%28Python%29

    Personally, I'd check to make sure that the second bound is on the opposite side of the term as the first bound (in rare cases where we shouldn't have neglected the (1-phi)**n term; you could possibly have do to another lookup seeing if the term is bounded by e.g., fib_array[n+1] and fib_array[n+2]). (This check may be redundant; but you'd have to prove that first, and the one extra comparison to be safe seems worth it in my book).

    0 讨论(0)
  • 2021-02-02 14:25

    Use the closed form formula: http://en.wikipedia.org/wiki/Fibonacci_number#Closed-form_expression

    Then binary search

    0 讨论(0)
提交回复
热议问题