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
Build a table of Fibonacci numbers that will fit in 8 bytes; there's only 94. That will save you calculating them through each iteration. There's no need for floating point math here.
Then use a binary search to find the number below and above your number in the time. That will save you comparing all the numbers, and reduce your search to a constant search time.
This meets your requirements, but note that your requirements do not specify what should be returned for N such that there is no Q in 64 bit integer space, i.e. N > 12,200,160,415,121,876,738. If you care about that, decide how you want to handle it. :)
#include "stdint.h"
#include "stdio.h"
#include "stdlib.h"
#include "time.h"
/* build a table of all fibonacci numbers that fit in a uint64_t. */
static const int fibonacciCount = 94;
uint64_t fibonacciSequence[fibonacciCount];
static void precalc(void) {
fibonacciSequence[0] = 0;
fibonacciSequence[1] = 1;
for (int i = 2; i < fibonacciCount; ++i) {
fibonacciSequence[i] = fibonacciSequence[i-2] + fibonacciSequence[i-1];
}
}
/* do a binary search for the Fibonacci numbers >= N and <= N */
static void find_closest_fibonacci(uint64_t N, uint64_t *P, uint64_t *Q) {
int upper = fibonacciCount;
int lower = 0;
do {
int mid = ((upper - lower) >> 1) + lower;
uint64_t midValue = fibonacciSequence[mid];
if ( midValue > N ) {
upper = mid;
} else if ( midValue < N ) {
lower = mid + 1;
} else {
*P = fibonacciSequence[ mid ];
*Q = fibonacciSequence[ mid ];
return;
}
} while ( upper > lower );
*P = fibonacciSequence[ lower - 1 ];
*Q = fibonacciSequence[ lower ];
}
/* hacked together 64 bit random number generator,
used just in tester only */
static uint64_t rand64(void) {
/* totally flawed as a random number generator,
but that's not the point here. */
uint64_t v = 0;
for (int i = 0; i < 8; ++i) {
v = (v << 8) + (rand() % 256);
}
return v;
}
int main (int argc, const char * argv[]) {
srand( (unsigned)time( NULL ) );
precalc(); /* do this once only */
uint64_t upperBound = fibonacciSequence[fibonacciCount - 1];
printf( "Upper bound is %qu\n", upperBound );
/* build a sample to run against the algorithm
we favor mostly numbers below RAND_MAX, because
if we test across all of UINT64_MAX the results are
pretty boring. */
static const int sampleCount = 100;
static const int normalSampleCount = 90;
uint64_t numbers[sampleCount];
for (int i = 0; i < normalSampleCount; ++i) {
numbers[i] = rand();
}
for (int i = normalSampleCount; i < sampleCount; ++i) {
uint64_t number;
do {
number = rand64();
} while ( number > upperBound );
numbers[i] = number;
}
/* use described algorithm */
for (int i = 0; i < 100; ++i) {
uint64_t P;
uint64_t Q;
uint64_t N = numbers[i];
find_closest_fibonacci(N, &P, &Q);
printf( "%qu [%qu,%qu]\n", N, P, Q );
}
return 0;
}
Put whatever other algorithm you have in the same file, and run it against the same tester.