简体   繁体   English

优化找到特定斐波那契数的算法

[英]Optimize a algorithm that find a specific Fibonacci number

Given an number A , I want to find the Ath Fibonacci number that is multiple of 3 or if the number representation has at least a 3 on it. 给定数字A ,我想找到3的倍数的Ath斐波那契数,或者如果数字表示形式上至少有3的话。

Example: 例:

Fibonacci > 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, ... 斐波那契> 0、1、1、2、3、5、8、13、21、34、55、89、144、233,...

Input: 1, Output: 3; 输入:1,输出:3;

3 is the first Fibonacci number that is multiple of 3 or has an 3 on it. 3是第一个斐波那契数,它是3的倍数或上面有3的数字。

Input: 3, Output: 21; 输入:3,输出:21;

21 is the third Fibonacci number that is multiple of 3 or has an 3 on it. 21是第三个斐波那契数,它是3的倍数或上面有3的数字。

Edit: Variable type changed to unsigned long long int and ajust on Fibonacci generator. 编辑:变量类型更改为unsigned long long int,并且在Fibonacci生成器上为ajust。 Thanks @rcgldr and @Jarod42 for the help! 感谢@rcgldr和@ Jarod42的帮助!

My code: 我的代码:

#include<bits/stdc++.h>

using namespace std;

int tem(unsigned long long int i){

    while(i != 0){
        if(i%10 == 3){
            return true;
        }
        i = i/10;
    }
    return false;
}

int main(){

    int a, count = 0;
    unsigned long long int f1 = 1, f2 = 1;

    while(scanf("%d", &a) != EOF){
        for(unsigned long long int i = 2; i > 0; i++){
            i = f1 + f2;
            f1 = f2;
            f2 = i;
                if((i%3 == 0) || tem(i)){
                    count++;
                    if(count == a){
                        cout << i << endl;
                        break;
                    }
                }

        }
    }
}

When A > 20, it starts to slow down. 当A> 20时,它开始变慢。 Makes sense because it tends to be exponecial. 很有道理,因为它倾向于指数级。 My code is not very efficient, but I didn't find an better logic to use. 我的代码效率不是很高,但是我没有找到更好的逻辑。

I looked into these links, but didn't find an conclusion: 我调查了这些链接,但没有得出结论:

1 - Recursive Fibonacci 1- 递归斐波那契

2 - Fibonacci Optimization 2- 斐波那契优化

Any ideas? 有任何想法吗? Thanks for the help! 谢谢您的帮助!

You can speed up the Fibonacci part using this sequence 您可以按照以下顺序加快斐波那契零件的速度

uint64_t f0 = 0;    // fib( 0)
uint64_t f1 = 1;    // fib(-1)
int n = ... ;       // generate fib(n)
    for(int i = 0; i < n; i++){
        std::swap(f0,f1);
        f0 += f1;
    }

Note Fib(93) is the maximum Fibonacci number that fits in a 64 bit unsigned integer, it also has a 3 in it. 注意Fib(93)是适合64位无符号整数的最大斐波那契数,其中也有3。 Fib(92) is the maximum Fibonacci number that is a multiple of 3. Fib(92)是最大斐波那契数,是3的倍数。

I used this example code to find all of the values ( a ranges from 0 to 62), it seems to run fairly fast, so I'm not sure what the issue is. 我用这个例子的代码来找到所有的值( a范围为0〜62),它似乎运行速度相当之快,所以我不知道是什么问题。 Is optimization enabled? 是否启用优化?

#include <iostream>
#include <iomanip>

typedef unsigned long long uint64_t;

int tem(uint64_t i){
    while(i != 0){
        if(i%10 == 3)
            return true;
        i = i/10;
    }
    return false;
}

int main(){
    int a = 0, n;
    uint64_t f0 = 1, f1 = -1;  // fib(-1), fib(-2)

    for(n = 0; n <= 93; n++){
        std::swap(f0, f1);     // f0 = next fib
        f0 += f1;
        if((n&3) == 0 || tem(f0)){
            std::cout << std::setw( 2) << a << " " 
                      << std::setw( 2) << n << " "
                      << std::setw(20) << f0 << std::endl;
            a++;
        }
    }
    return 0;
}

Depending on the compiler, i%10 and i/10 may use a multiply by "magic number" and shift to replace divide by a constant. 根据编译器的不同,i%10和i / 10可能会使用乘以“幻数”并将其移位以用常数替换除数。 Code generated by Visual Studio 2015 for tem(), which is fairly "clever": 由Visual Studio 2015为tem()生成的代码,该代码相当“聪明”:

tem     proc                                ;rcx = input
        test    rcx,rcx                     ; return false if rcx == 0
        je      SHORT tem1
        mov     r8, 0cccccccccccccccdh      ;magic number for divide by 10
tem0:   mov     rax, r8                     ;rax = magic number
        mul     rcx                         ;rdx = quotient << 3
        shr     rdx, 3                      ;rdx = quotient
        lea     rax, QWORD PTR [rdx+rdx*4]  ;rax = quotient*5
        add     rax, rax                    ;rax = quotient*10
        sub     rcx, rax                    ;rcx -= quotient * 10 == rcx % 10
        cmp     rcx, 3                      ;br if rcx % 10 == 3
        je      SHORT tem2
        mov     rcx, rdx                    ;rcx = quotient  (rcx /= 10)
        test    rdx, rdx                    ;loop if quotient != 0
        jne     SHORT tem0
tem1:   xor     eax, eax                    ;return false
        ret     0

tem2:   mov     eax, 1                      ;return true
        ret     0

tem     endp

Just pointing out some obvious coding errors 只是指出一些明显的编码错误

for(unsigned long long int i = 2; i > 0; i++)

is redundant. 是多余的。

for(;;){ 
  unsigned long long i = f1+f2;

should suffice. 应该足够了。 Secondly 其次

return 0; 

is meaningless because it breaks out of the while loop. 是没有意义的,因为它打破了while循环。 A break would be better. break会更好。

There's a clever way to do Fibonacci. 有一种做斐波那契的聪明方法。

http://stsievert.com/blog/2015/01/31/the-mysterious-eigenvalue/ http://stsievert.com/blog/2015/01/31/the-mysterious-eigenvalue/

Code's in python and is just for the nth number, but I think you get the idea. 代码在python中,仅用于第n个数字,但我想您明白了。

def fib(n):
    lambda1 = (1 + sqrt(5))/2
    lambda2 = (1 - sqrt(5))/2
    return (lambda1**n - lambda2**n) / sqrt(5)
def fib_approx(n)
    # for practical range, percent error < 10^-6
    return 1.618034**n / sqrt(5)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM