【问题标题】:Fast doubling and fibonacci algorithm explanation快速加倍和斐波那契算法解释
【发布时间】:2020-04-11 03:31:06
【问题描述】:

在研究矩阵求幂时,我遇到了快速加倍和下面的实现。我有以下问题:

  1. 为什么 for 循环会从 31 向下迭代到 0?

  2. 条件句中用i屏蔽n的目的是什么?

    private static BigInteger Fibonacci(int n) {
        BigInteger a = BigInteger.Zero;
        BigInteger b = BigInteger.One;
        for (int i = 31; i >= 0; i--) {
            BigInteger d = a * (b * 2 - a);
            BigInteger e = a * a + b * b;
            a = d;
            b = e;
            if ((((uint)n >> i) & 1) != 0) {
                BigInteger c = a + b;
                a = b;
                b = c;
            }
        }
        return a;
    }

请链接任何可以帮助我深入理解该主题的参考资料或文献。

干杯!

【问题讨论】:

标签: algorithm bit-manipulation fibonacci


【解决方案1】:

你的代码中循环的不变量是:

a = Fib(n/2^i)
b = Fib(n/2^i + 1)

(这里^ 是取幂而不是异或)。

您可以使用快速倍增公式检查这些不变量是否随着 i 的变化而成立:

Fib(2k) = 2Fib(k)*Fib(k+1) - Fib(k)*Fib(k)
Fib(2k+1) = Fib(k+1)*Fib(k+1) + Fib(k)*Fib(k)

当 n/2^i 为奇数时,if 语句应用公式:

Fib(2k+1), Fib(2k+2) = Fib(2k+1), Fib(2k) + Fib(2k+1)

(这只是常规的斐波那契公式)。

将代码视为此递归代码的自上而下(而不是自下而上)版本可能会有所帮助:

def fib2(n):
    if n == 0:
        return 0, 1
    a, b = fib2(n//2)
    a, b = a*(b*2 - a), a*a + b*b
    if n % 2 != 0:
        a, b = b, a+b
    return a, b

唯一显着的区别是,这段代码在 n 为 0 之前递归,而自上而下的代码总是迭代 32 次。

【讨论】:

    【解决方案2】:
    1. 为什么迭代器会从 31 循环到 0?

    回答。因为程序员以 32 位(范围从 0 到 31)存储数据。从31到0的意思是从最低位到最高位迭代。

    1. 在条件句中用 i 屏蔽 n 的目的是什么?

    回答。这实际上不是掩蔽。它是一个左移运算符。整体表达式if ((((uint)n >> i) & 1) != 0) 检查数字 n 是否有奇偶校验位要添加到下一个有效位中。

    您想学习的主题称为位操作。以下是我第一次自学位操作的一些资源。

    【讨论】:

    • 感谢您的链接/输入。 n >> i 不是右移ni吗?此外,& 1 将向 LSB 添加 1 或 0。整个表达式 ((n >> i) & 1) != 0 等价于 n/2^i % 2 != 0。
    • 是的,n>>i 是将 n 右移 i。第二个表达也是正确的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-06
    • 2012-11-29
    • 2020-01-18
    • 1970-01-01
    • 2016-06-27
    • 2019-06-26
    • 2013-03-31
    相关资源
    最近更新 更多