https://blog.paulhankin.net/fibonacci/

This code, somewhat surprisingly, generates Fibonacci numbers.

def fib(n):
return (4 << n*(3+n)) // ((4 << 2*n) - (2 << n) - 1) & ((2 << n) - 1)

In this blog post, I'll explain where it comes from and how it works.

Before getting to explaining, I'll give a whirlwind background overview of Fibonacci numbers and how to compute them. If you're already a maths whiz, you can skip most of the introduction, quickly skim the section "Generating functions" and then read "An integer formula".

Overview

The Fibonacci numbers are a well-known sequence of numbers:

\[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, \ldots
\]

The nth number in the sequence is defined to be the sum of the previous two, or formally by this recurrence relation:

\[\begin{eqnarray}
\mathrm{Fib}(0) &=& 1 \\
\mathrm{Fib}(1) &=& 1 \\
\mathrm{Fib}(n) &=& \mathrm{Fib}(n - 1) + \mathrm{Fib}(n - 2)
\end{eqnarray}
\]

I've chosen to start the sequence at index 0 rather than the more usual 1.

Computing Fibonacci numbers

There's a few different reasonably well-known ways of computing the sequence. The obvious recursive implementation is slow:

def fib_recursive(n):
if n < 2: return 1
return fib_recursive(n - 1) + fib_recursive(n - 2)

An iterative implementation works in O(n) operations:

def fib_iter(n):
a, b = 1, 1
for _ in xrange(n):
a, b = a + b, a
return b

And a slightly less well-known matrix power implementation works in O(log n) operations.

def fib_matpow(n):
m = numpy.matrix('1 1 ; 1 0') ** n
return m.item(0)

The last method works by considering the a and b in fib_iter as sequences, and noting that

\[\left(\begin{matrix}
a_{n+1} \\
b_{n+1} \\
\end{matrix}\right) =
\left(\begin{matrix}
1 & 1 \\
1 & 0 \\
\end{matrix}\right)
\left(\begin{matrix}
a_n \\
b_n \\
\end{matrix}\right)
\]

From which follows

\[\left( \begin{array}{c}
a_{n} \\
b_{n} \end{array} \right) =
\left( \begin{array}{cc}
1 & 1 \\
1 & 0 \end{array} \right) ^ n
\left( \begin{array}{c}
1 \\
1 \end{array} \right)
\]

and so if \(m = \left(\begin{matrix}
1 & 1 \\
1 & 0 \end{matrix} \right)^n\) then \(b_n = m_{11}\) (noting that unlike Python, matrix indexes are usually 1-based).

It's O(log n) based on the assumption that numpy's matrix power does something like exponentation by squaring.

Another method is to find a closed form for the solution of the recurrence relation. This leads to the real-valued formula: Fib(n)=(ϕn+1−ψn+1)/5‾√) where ϕ=(1+5‾√)/2 and ψ=(1−5‾√)/2. The practical flaw in this method is that it requires arbitrary precision real-valued arithmetic, but it works for small n.

def fib_phi(n):
phi = (1 + math.sqrt(5)) / 2.0
psi = (1 - math.sqrt(5)) / 2.0
return int((phi ** (n+1) - psi ** (n+1)) / math.sqrt(5))

Generating Functions

A generating function for an arbitrary sequence an is the infinite sum Σnanxn. In the specific case of the Fibonacci numbers, that means ΣnFib(n)xn. In words, it's an infinite power series, with the coefficient of xn being the nth Fibonacci number.

Now,

Fib(n+2)=Fib(n+1)+Fib(n)

Multiplying by xn+2 and summing over all n, we get:

ΣnFib(n+2)xn+2=ΣnFib(n+1)xn+2+ΣnFib(n)xn+2

If we let F(x) to be the generating function of Fib, which is defined to be ΣnFib(n)xn then this equation can be simplified:

F(x)−x−1=x(F(x)−1)+x2F(x)

and simplifying,

F(x)=xF(x)+x2F(x)+1

We can solve this equation for F to get

F(x)=11−x−x2

It's surprising that we've managed to find a small and simple formula which captures all of the Fibonacci numbers, but it's not yet obvious how we can use it. We'll get to that in the next section.

A technical aside is that we're going to want to evaluate F at some values of x, and we'd like the power series to converge. We know the Fibonacci numbers grow like ϕn and that geometric series Σnan converge if |a|<1, so we know that if |x|<1/ϕ≃0.618 then the power series converges.

An integer formula

Now we're ready to start understanding the Python code.

To get the intuition behind the formula, we'll evaluate the generating function F at 10−3.

F(x)=11−x−x2F(10−3)=11−10−3−10−6=1.001002003005008013021034055089144233377610988599588187…

Interestingly, we can see some Fibonacci numbers in this decimal expansion: 1,1,2,3,5,8,13,21,34,55,89. That seems magical and surprising, but it's because F(10−3)=Fib(0)+Fib(1)/103+Fib(2)/106+Fib(3)/109+….

In this example, the Fibonacci numbers are spaced out at multiples of 1/1000, which means once they start getting bigger that 1000 they'll start interfering with their neighbours. We can see that starting at 988 in the computation of F(10−3) above: the correct Fibonacci number is 987, but there's a 1 overflowed from the next number in the sequence causing an off-by-one error. This breaks the pattern from then on.

But, for any value of n, we can arrange for the negative power of 10 to be large enough that overflows don't disturb the nth Fibonacci. For now, we'll just assume that there's some k which makes 10−k sufficient, and we'll come back to picking it later.

Also, since we'd like to use integer maths (because it's easier to code), let's multiply by 10kn, which also puts the nth Fibonacci number just to the left of the decimal point, and simplify the equation.

10knF(10−k)=10kn1−10−k−10−2k=10kn+2k102k−10k−1

If we take this result modulo 10k, we'll get the nth Fibonacci number (again, assuming we've picked k large enough).

Before proceeding, let's switch to base 2 rather than base 10, which changes nothing but will make it easier to program.

2knF(2−k)=2k(n+2)22k−2k−1

Now all that's left is to pick a value of k large enough so that Fib(n+1)<2k. We know that the Fibonacci numbers grow like ϕn, and ϕ<2, so k=n+1 is safe.

So! Putting that together:

Fib(n)≡2(n+1)nF(2−(n+1)) mod 2n+1≡2(n+1)(n+2)(2n+1)2−2n+1−1 mod 2n+1≡2(n+1)(n+2)22n+2−2n+1−1 mod 2n+1

If we use left-shift notation that's available in python, where a<<k=a⋅2k then we can write this as:

Fib(n)≡4<<n(3+n)(4<<2n)−(2<<n)−1mod (2<<n)

Observing that mod (2<<n) can be expressed as the bitwise and (&) of (2<<n)−1, we reconstruct our original Python program:

def fib(n):
return (4 << n*(3+n)) // ((4 << 2*n) - (2 << n) - 1) & ((2 << n) - 1)

Although it's curious to find a non-iterative, closed-form solution, this isn't a practical method at all. We're doing integer arithmetic with integers of size O(n2) bits, and in fact, before performing the final bit-wise and, we've got an integer that is the first n Fibonacci numbers concatenated together!

AN INTEGER FORMULA FOR FIBONACCI NUMBERS的更多相关文章

  1. Fibonacci Numbers

    Fibonacci Numbers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...

  2. UVa-11582:Colossal Fibonacci Numbers!(模算术)

    这是个开心的题目,因为既可以自己翻译,代码又好写ヾ(๑╹◡╹)ノ" The i’th Fibonacci number f(i) is recursively defined in the f ...

  3. [Amazon] Program for Fibonacci numbers 斐波那契数列

    The Fibonacci numbers are the numbers in the following integer sequence. 0, 1, 1, 2, 3, 5, 8, 13, 21 ...

  4. codeforces 446C DZY Loves Fibonacci Numbers(数学 or 数论+线段树)(两种方法)

    In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation F1 ...

  5. Codeforces 446-C DZY Loves Fibonacci Numbers 同余 线段树 斐波那契数列

    C. DZY Loves Fibonacci Numbers time limit per test 4 seconds memory limit per test 256 megabytes inp ...

  6. cf446C DZY Loves Fibonacci Numbers

    C. DZY Loves Fibonacci Numbers time limit per test 4 seconds memory limit per test 256 megabytes inp ...

  7. Codeforces Round #FF 446 C. DZY Loves Fibonacci Numbers

    參考:http://www.cnblogs.com/chanme/p/3843859.html 然后我看到在别人的AC的方法里还有这么一种神方法,他预先设定了一个阈值K,当当前的更新操作数j<K ...

  8. HDU 3117 Fibonacci Numbers(围绕四个租赁斐波那契,通过计++乘坐高速动力矩阵)

    HDU 3117 Fibonacci Numbers(斐波那契前后四位,打表+取对+矩阵高速幂) ACM 题目地址:HDU 3117 Fibonacci Numbers 题意:  求第n个斐波那契数的 ...

  9. Codeforces446C - DZY Loves Fibonacci Numbers

    Portal Description 给出一个\(n(n\leq3\times10^5)\)个数的序列,进行\(m(m\leq3\times10^5)\)次操作,操作有两种: 给区间\([L,R]\) ...

随机推荐

  1. anyRTC Web SDK 实现音视频呼叫功能

    前言 大家好,今天小编带给大家一个基于 anyRTC Web SDK 实现音视频呼叫的功能(本项目采用vue开发). 前提条件 在开始写代码之前还需要做一些准备工作,如果你之前没有使用过 anyRTC ...

  2. 使用 C++ WinRT 组件

    创建 C++ WinRT 组件 通过 Cpp/WinRT 项目模板创建一个 WinRT 组件工程 CppWinrtComponent.vcxproj,主要接口定义如下: namespace CppWi ...

  3. ssrf解题记录

    ssrf解题记录 最近工作需要做一些Web的代码审计,而我Web方面还比较薄弱,决定通过一些ctf的题目打打审计基础,练练思维,在博客上准备开几个专题专门记录刷题的过程. pwn题最近做的也很少,也要 ...

  4. 关于修改.net core webapi中null默认返回的状态码。

    在asp .net core webapi中,http请求的响应数据如果是null的话,我们知道状态码会返回204,即NoContent,为什么会出现这种情况呢?   因为在返回响应数据的时候,nul ...

  5. dubbo学习实践(3)之Dubbo整合Consul及Dubbo配置方式

    前言:上一篇中,已经写到了使用zookeeper为注册中心的配置,下面写下配置Consul为注册中心 1. Consul注册中心验证 修改provider和consumer的服务配置文件 Provid ...

  6. DrJava试用笔记

    安装方便:只要配好JAVA_HOME,用java -jar drjava-stable-20120818-r5686.jar即可启动,算是绿色软件: 特色功能:交互式命令行,可以在调试程序时改变变量值 ...

  7. git submodule 操作

    git submodule foreach git status 举一反三,对所有子库的操作,都可以使用 git submodule foreach 做前缀 foreach,可以记忆为for each ...

  8. SpringMVC学习09(文件的上传和下载)

    文件上传和下载 准备工作 文件上传是项目开发中最常见的功能之一 ,springMVC 可以很好的支持文件上传,但是SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况 ...

  9. 新版数据库分页方法(Sql server2012)

    1. ROW_NUMBER() 的分页方法 dbcc freeproccache dbcc dropcleanbuffers set statistics time on set statistics ...

  10. 从跨域与同源策略谈CSRF防御与绕过

    之前偶然看到群里有小伙汁问这个token相关的问题,当时我酝酿了一下子,没想好怎么总结,今天来说一下 CSRF在过去还属于OWASP TOP10 ,现在已经不是了(补充一点:关于OWASP API 请 ...