建立一个包含 8 个字节的斐波那契数列;只有 94 个。这样可以节省您在每次迭代中计算它们的时间。这里不需要浮点数学。
然后使用二分法查找时间中你的数字下方和上方的数字。这将节省您比较所有数字的时间,并将您的搜索减少到恒定的搜索时间。
这符合您的要求,但请注意,您的要求并未指定应为 N 返回的内容,因此 64 位整数空间中没有 Q,即 N > 12,200,160,415,121,876,738。如果您关心它,请决定如何处理它。 :)
#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;
}
将您拥有的任何其他算法放在同一个文件中,然后针对同一个测试器运行它。