斐波纳契数,如何找到数字(java)

时间:2016-04-11 13:47:21

标签: java math fibonacci

我的任务是找到Fibonacci列表的第一个非零成员的索引,该列表可以被这个值整除(在下面的示例中,值为:17 12 61)。所以我创建了Fibonacci序列,通过划分每个成员的序列并检查余数为零:

    public static void main(String[] args) {

    String stringInputValues = "17 12 61";
    Scanner scan = new Scanner(stringInputValues);

    int i = 0;
    BigInteger value = BigInteger.ZERO;;

    //start create Fibonacci numbers
    int N = 9000;
    BigInteger[] fibArray = new BigInteger[N + 1];
    fibArray[0] = BigInteger.ZERO;
    fibArray[1] = BigInteger.ONE;
    for (i = 2; i <= N; i++) {
        fibArray[i] = fibArray[i - 1].add(fibArray[i - 2]);

    }
    //end create Fibonacci numbers
    while (scan.hasNext()) {
        value = BigInteger.valueOf(scan.nextLong());
        for (i = 0; i <= fibArray.length - 1; i++) {
            if (i > 0 && fibArray[i].remainder(value) == BigInteger.ZERO) {

                System.out.println(i);
                break;
            }
        }
    }
}

这不适用于分隔符的大值(数字如此之大,以至于 java.lang.OutOfMemoryError:Java堆空间),例如 233328 433156 1032566 而不是 17 12 61 我觉得我的算法太简单而且效率低下。你能帮我更有效吗? 谢谢!

3 个答案:

答案 0 :(得分:1)

您可以使用JVM命令增加堆空间来解决您的问题。但是你的程序仍然是如此记忆力,换句话说效率非常低。如

java -Xmx256m MyProgram.java

设置256m的最大堆空间。

我建议你,在创建斐波纳契数时检查余数。这样你就永远不会创造超出你需要的东西。并且为了确保在没有合适的分隔符时不使用太多堆,请使用停止条件。

注意BigInteger使用4N + 64Bytes之类的数字来表示数字N.这是因为它在内部存储为int[],并且每个int都在JAVA中定义是4 Bytes

但第9000个斐波那契数字仍然很大......

EDIT(2): 表示第9000个Fibonacci数需要196个,因为第9000个Fibonacci数需要6248个比特来表示。由于Java中的每个int都是4字节,因此对于int []≡BigInteger数字,我们最终会得到784 + 64 = 848 Bytes。这几乎是1KB。

答案 1 :(得分:1)

关键是一次计算一个Fibonacci数。该解决方案有一个方法,它返回可被参数整除的Fibonacci数的索引:

import java.math.BigInteger;

public class FibonacciDivider {

    public static void main(String [] args) {
        int [] input = {233328, 433156, 1032566};
        for (int val: input) {
            System.out.println("index of Fibo. num. divisible by " + val +
                    ": " +  findIndexOfFibonacciWithDivisor(BigInteger.valueOf(val)));
        }
    }

    public static int findIndexOfFibonacciWithDivisor(BigInteger divisor) {
        BigInteger a = BigInteger.ZERO;
        BigInteger b = BigInteger.ONE;
        int index = 0;
        while (true) {
            index++;
            BigInteger c = b.add(a);
            // the mod() method returns the remainder
            if (c.mod(divisor).equals(BigInteger.ZERO)) return index;
            a = b;
            b = c;
        }
    }
}

输出(到目前为止!)是:

index of Fibo. num. divisible by 233328: 1619
index of Fibo. num. divisible by 433156: 281

它仍然在1032566上启动!

更新:index of Fibo. num. divisible by 1032566: 1548851

答案 2 :(得分:0)

第9000个斐波那契数字相当大。可能,它有足够的内存来生成9000个内存,但BigInteger除法运算繁重,可能需要大量内存(和时间)。

介绍Iterator而不是生成9000个数字。也许,有一些与斐波那契数字可分性相关的数学技巧。

如果您不必自己输出数字,但只想知道它是否存在,则必须使用模运算并完全避免使用BigInteger。只需计算斐波那契数的模数。