我正在尝试将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]范围内的任何整数。
答案 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);