斐波纳契系列f(93)处的数值具有负值,怎么样?

时间:2014-02-10 00:26:19

标签: java arrays long-integer fibonacci

我正在尝试将fibonacci系列打印到“N”个数字。所有的工作按照期望直到f(92)但是当我试图得到f(93)的值时,值结果为负:“ - 6246583658587674878”。这怎么可能?下面的逻辑中有什么错误?

public long fibo(int x){
    long[] arr = new long[x+1];
    arr[0]=0;
    arr[1]=1;
    for (int i=2; i<=x; i++){
        arr[i]=arr[i-2]+arr[i-1];
    }
    return arr[x];
}

f(91) = 4660046610375530309
f(92) = 7540113804746346429    
f(93) = -6246583658587674878

这是因为数据类型吗?我应该用什么数据类型将fibonacci系列打印到N个数字? N可以是[0..10,000,000]范围内的任何整数。

3 个答案:

答案 0 :(得分:6)

您遇到了integer overflow

 4660046610375530309 <-- term 91
+7540113804746346429 <-- term 92
====================
12200160415121876738 <-- term 93: the sum of the previous two terms
 9223372036854775808 <-- maximum value a long can store

要避免这种情况,请使用BigInteger,它可以处理任意数量的数字 这是您的实现转换为使用BigDecimal

public String fibo(int x){
    BigInteger[] arr = new BigInteger[x+1];
    arr[0]=BigInteger.ZERO;
    arr[1]=BigInteger.ONE;
    for (int i=2; i<=x; i++){
        arr[i]=arr[i-2].add(arr[i-1]);
    }
    return arr[x].toString();u
}

请注意,返回类型必须是String(或BigInteger),因为即使x的适度值93也会产生对任何java基元来说都太大的结果。

答案 1 :(得分:4)

这是因为long类型溢出。换句话说:计算的数字太大而不能表示为long,并且由于用于整数类型的two's complement表示,在发生溢出后,该值变为负数。要更好地了解正在发生的事情,请查看以下代码:

System.out.println(Long.MAX_VALUE);
=> 9223372036854775807  // maximum long value
System.out.println(Long.MAX_VALUE + 1);
=> -9223372036854775808 // oops, the value overflowed!

fibo(93)的值为12200160415121876738,明显大于long中的最大值。

这是整数在计算机程序中工作的方式,毕竟它们是有限的,不可能是无限的。一种可能的解决方案是使用BigInteger来实现该方法(而不是long),它是一个用于在Java中表示任意精度整数的类。

答案 2 :(得分:0)

正如以上答案中正确指出的那样,您遇到了溢出问题,但是使用下面的Java 8代码段可以打印系列。

Stream.iterate(new BigInteger[] {BigInteger.ZERO, BigInteger.ONE}, t -> new BigInteger[] {t[1], t[0].add(t[1])})
        .limit(100)
        .map(t -> t[0])
        .forEach(System.out::println);