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. Beautiful Soup4.4.0中文官方文档!最权威的参考---中文官方文档

    最好用的解析库Beautiful Soup 解析库-----中文官方文档 https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/

  2. git学习心得之git跨分支提交代码

    最近在工作中遇到了git跨分支提交代码的问题,本地拉的是远程master分支的代码,需要将本地修改代码提交到远程temp分支. 1.在gitlab上对相应项目fork本地分支 2.更新本地代码,将远程 ...

  3. 防止因提供的sql脚本有问题导致版本bvt失败技巧

    发版本时,可能会由于测试库和开发库表结构不一样而导致数据库脚本在测试那边执行时出错,导致版本BVT失败,以下技巧可解决此问题. 步骤:备份目标库,在备份库中执行将要提供的sql脚本看有无问题,若没问题 ...

  4. SpringCloud升级之路2020.0.x版-3.Eureka Server 与 API 网关要考虑的问题

    本系列为之前系列的整理重启版,随着项目的发展以及项目中的使用,之前系列里面很多东西发生了变化,并且还有一些东西之前系列并没有提到,所以重启这个系列重新整理下,欢迎各位留言交流,谢谢!~ 之前我们提到了 ...

  5. 大数据学习(05)——MapReduce/Yarn架构

    Hadoop1.x中的MapReduce MapReduce作为Hadoop最核心的两个组件之一,在1.0版本中就已经存在了.它包含这么几个角色: Client 多数情况下Client的作用就是向服务 ...

  6. Netty入门(一):ByteBuf

    网络数据的基本单位总是字节.Java NIO 提供了 ByteBuffer 作为它的字节容器,但是这个类使用起来过于复杂,而且也有些繁琐.Netty 的 ByteBuffer 替代品是 ByteBuf ...

  7. CSS 即将支持嵌套,SASS/LESS 等预处理器已无用武之地?

    最近,有一则非常振奋人心的消息,CSS 即将原生支持嵌套 -- Agenda+ to publish FPWD of Nesting,表示 CSS 嵌套规范即将进入规范的 FWPD 阶段. 目前对应的 ...

  8. 面试必备:Android Activity启动流程源码分析

    最近大致分析了一把 Activity 启动的流程,趁着今天精神状态好,把之前记录的写成文章. 开门见山,我们直接点进去看 Activity 的 startActivity , 最终,我们都会走到 st ...

  9. 使用各类BeanUtils的时候,切记注意这个坑!

    在日常开发中,我们经常需要给对象进行赋值,通常会调用其set/get方法,有些时候,如果我们要转换的两个对象之间属性大致相同,会考虑使用属性拷贝工具进行. 如我们经常在代码中会对一个数据结构封装成DO ...

  10. MySQL Mac 终端环境变量配置

    MySQL Mac 终端环境变量配置 这里安装的是mysql-8.0.26-macos11-x86_64,M1Mac,原本打算安装arm64版本,但一直安装不了,就装了x86版本 安装完成MySQL之 ...