【问题标题】:Fibonacci numbers, how to find the number (java)斐波那契数,如何找到数字(java)
【发布时间】:2016-04-11 13:47:20
【问题描述】:

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

    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 heap space),例如 233328 433156 1032566 而不是 17 12 61 我觉得我的算法太简单了,效率低下。你能帮我做一个更有效的吗? 谢谢!

【问题讨论】:

  • 它不起作用怎么办?只是时间太长了?这可能属于codereview
  • 是的。数字很​​大,我收到消息:线程“main”java.lang.OutOfMemoryError 中的异常:Java 堆空间
  • 我猜你没有停止条件。

标签: java math fibonacci


【解决方案1】:

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

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】:

    您可以通过使用 JVM 命令增加堆空间来解决您的问题。但是你的程序仍然是一个内存猪,换句话说,效率非常低。比如

    java -Xmx256m MyProgram.java
    

    设置256m的最大堆空间。

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

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

    但第 9000 个斐波那契数仍然是巨大的..


    编辑(2): 表示第 9000 个斐波那契数需要 196 个整数,因为第 9000 个斐波那契数需要 6248 位来表示。由于 Java 中的每个 int 都是 4 字节,因此我们将在 int[] ≡ BigInteger 数字中以 784 + 64 = 848 Bytes 结束。这几乎是1KB。

    【讨论】:

    • 是的。同意。我在找算法,你能描述一下这个任务的有效算法吗?
    • 哇 -- 你是如何计算出这个数字需要多少口的?
    • 字节不是位(如果不是拼写错误)。好吧,首先我将 BigInteger 转换为#bytes,然后将其转换为 YB。
    • 不确定你的逻辑是否正确;我的代码输出到第 1548851 个斐波那契数并且没有遇到内存异常。 (我的机器没有YB内存)
    • @BrianRisk 是的,你说得对,我修好了。我没有将其正确转换为 int
    【解决方案3】:

    第 9000 个斐波那契数相当大。可能,它的内存足以生成 9000 个,但BigInteger 除法操作繁重,可能会占用大量内存(和时间)。

    引入Iterator,而不是生成 9000 个数字。也许,有一些与斐波那契数除法有关的数学技巧。

    如果您不必输出数字本身而只想判断它是否存在,则必须使用模运算并完全避免BigIntegers。只需计算斐波那契数的模数。

    【讨论】:

    • 嗯,我想过模运算,但不知道如何实现。
    • @SergeyLotvin Easy:只保留模数,而不是完整的数字。请记住(a + b) % m == a % m + b % m。使用ints 或longs 并在每次操作后取模。在您的情况下,F[i] = (F[i-1] + F[i-2]) % m;。然后只需将模数与零进行比较。
    • @SergeyLotvin 我刚刚重读了声明。它旨在让您使用模运算。
    猜你喜欢
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    • 2020-01-18
    • 1970-01-01
    • 2017-04-02
    • 2015-06-05
    • 2014-05-23
    • 2014-05-03
    相关资源
    最近更新 更多