此问题之前存在一些混淆。以前,原始海报和那些回应的人认为这是计算第n个斐波纳契数的破坏函数,但实际上它是一个计算第n个主要斐波那契数的函数,它是来自Stack Exchange的codegolf的编程谜题。
f(n){int i=1,j=0,k;for(;n;n-=k==i)for(j=i-j,i+=j,k=2;i%k&&k++<i;);return i;}
这是
中的C 76字符示例https://codegolf.stackexchange.com/questions/6994/find-the-nth-fibonnaci-prime-in-the-shortest-code
对于32位有符号整数,n的范围是1到10.前10个素数斐波纳契数是:2,3,5,13,89,233,1597,28657,514229,433494437。
问题是这个功能如何运作?
codegolf的原始资料不包括解释。这可能属于codegolf,但之前的问题是在SO处提出的,我希望上一个问题的海报会看到这个问题并回答他/她的问题。
答案 0 :(得分:3)
让我们先缩进它:
int f(int n)
{
int i = 1, j = 0, k;
for (; n; n -= k == i)
for (j = i - j, i += j, k = 2; i % k && k++ < i;) ;
return i;
}
对于合理的输入, n
非零,因此第一个循环将执行。请注意,k == i
尚未评估,因为第一个for
的正文必须先执行,因此k
未初始化并不重要。
有关此的更多数学演示,请注意j = f(0) = 0
和i = f(2) = 1
是第一个和第三个Fibonacci数。从n = 2
,j = f(n-2) = 0
,i = f(n) = 1
开始,为了推进j和i,我们有:
j = i - j = f(n) - f(n-2) = f(n-1)
i = i + j = f(n) + f(n-1) = f(n+1)
n = n + 1
对于每个外部循环,i
和j
将前进到内循环初始化中的下一个斐波那契数字。
j = 1 == f(1), i = 2 == f(3)
j = 1 == f(2), i = 3 == f(4)
j = 2 == f(3), i = 5 == f(5)
j = 3 == f(4), i = 8 == f(6)
j = 5 == f(5), i = 13 == f(7)
这证实了我们的模式:我们可以从前几次迭代中看到i
比j
提前两步。
i % k && k++ < i
这只是一个素性测试:它在k
等于i
时停止(如果i
为素数就会发生这种情况 - 同时k++ < i
在技术上永远不会失败是的,因为第一个条件将首先评估为false,但它具有有用的副作用)或k
是i
的正确除数(因此i
不是素数)。它不是最有效的,但它确实有效。
将k++
置于for
循环的条件部分可以正确地增加它并保存更多字符(好吧,我认为只有一个)。
n -= k == i
如果i
没有素数,则不会更改n
,因此将检查下一个斐波纳契数(因为i
迭代斐波纳契数列) 。如果i
是素数,那么它递减n
,它会减少我们找到的素数斐波那契数的数量,并且无论如何都会检查下一个素数。当它达到0
时,我们会找到n
。
问题是这个功能如何运作?
它的工作原理是顺序计算Fibonacci数并测试每个数的素数,直到它找到n
这样的素数。
一旦你清理了一点代码,就没什么特别的了。很大程度上只是很多人会写的强力算法,虽然由于素性检查而效率稍低,而且由于想要尽可能多地保存字符而难以阅读。
最突出的部分是i
和j
的计算,它使i
比j
提前两步。这个技巧也可能具有保存最多字符的效果。