Liste des Groupes | Revenir à cl c++ |
On Wed, 18 Dec 2024 01:33:42 +0200
Michael S <already5chosen@yahoo.com> wrote:
>I am pretty sure that better variant exists, but for tonight it's>
enough.
Morning fibs.
>
Recursive:
>
struct pair_t {
long long a,b;
};
>
// return .a=fib(n), .b=fib(n+1)
static struct pair_t fib2(long n)
{
if (n <= 0) {
struct pair_t ret = { .a = 0, .b = n==0 ? 1 : 0 };
return ret;
}
// for n > 0
// fib(n*2) = (fib(n-1)+fib(n+1))*fib(n)
// fib(n*2+1) = fib(n)*fib(n)+fib(n+1)*fib(n+1)
long m = (n-1) >> 1;
struct pair_t ret = fib2(m);
long long a = ret.a, b = ret.b;
long long c = a + b;
if ((n & 1)==0) { // (m,m+1) => ((m+1)*2,(m+1)*2*2+1)
ret.a = (a + c)*b;
ret.b = b*b + c*c;
} else { // (m,m+1) => (m*2+1,(m+1)*2)
ret.a = a*a + b*b;
ret.b = (a + c)*b;
}
return ret;
}
>
static long long fib(long n)
{
struct pair_t x = fib2(n-1);
return x.b;
}
Iterative:
>
static long long fib(long n)
{
if (n <= 0)
return 0;
// find MS bit
unsigned long tmp = n;
unsigned long bit = 1;
while (tmp > 1) {
bit += bit;
tmp /= 2;
}
// for n > 0
// fib(n*2) = (fib(n-1)+fib(n+1))*fib(n)
// fib(n*2+1) = fib(n)*fib(n)+fib(n+1)*fib(n+1)
long long a = 0, b = 1;
while (bit > 1) {
long long c = a + b; // fib(n+1)
bit /= 2;
if ((n & bit)==0) { // (n-1,n) => (n*2-1,n*2)
c += a;
a = a*a + b*b;
b = c*b;
} else { // (n-1,n) => (n*2,n*2+1)
a = (a + c)*b;
b = b*b + c*c;
}
}
return b;
}
>
>
Both variants above are O(log(n)).
In practice for n in range 0 to 92 my measurement gear does not detect
differences in speed vs simple loop. If anything, simple loop is a
little faster.
Les messages affichés proviennent d'usenet.