Java 多头中的斐波那契计算显示负数

Fibonacci calculation in Java Longs shows up negative

我的 Fibonacci 计算器工作正常,但是当数字上升到更高时,结果会变成负数,就像它超过最大值 Integer 一样。

它正在使用缓存 java.util.Map<Integer, Long>。进入 Map 的所有内容都完全符合预期,但是当打印出来时我得到例如对于 291:

-784134397488903422

根据http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibCalcX.html,应该是:

2923602405716568564338475449381171413803636207598822186175234

我的 Long 似乎出了点问题,但我还不确定具体是什么。有人能给我指出正确的方向吗?

Map 个条目的值: http://pastebin.com/uje07Ays

java 有 8 个 primitive data types

字节

  • 最小值为 -128 (-2^7)
  • 最大值为127(含)(2^7 -1)
  • 默认值为 0

  • 最小值为 -32,768 (-2^15)
  • 最大值为32,767(含)(2^15 -1)
  • 默认值为 0。
  • short数据类型也可以作为byte数据类型来保存内存。 short 比 int 小 2 倍(但java将此类型改为 int 进行计算)

整数

  • 最小值为 - 2,147,483,648。(-2^31)
  • 最大值为2,147,483,647(含).(2^31 -1),比你的数字多
  • Int 通常用作整数值的默认数据类型 除非担心内存问题。
  • 默认值为 0。

  • 最小值为-9,223,372,036,854,775,808。(-2^63)
  • 最大值为9,223,372,036,854,775,807(含)。 (2^63 -1) 这个值小于你的数字
  • 当需要比 int 更宽的范围时使用此类型。
  • 默认值为 0L。

浮动

  • Float 数据类型是单精度 32 位 IEEE 754 浮点数。
  • float主要用于大型浮点数组节省内存 数字。使用这种类型的 int 值是犯罪
  • 默认值为 0.0f。

  • double 数据类型是双精度 64 位 IEEE 754 浮点数 点.
  • 这种数据类型一般用作小数的默认数据类型 值,一般默认选择。
  • Double 数据类型不应该用于精确值,例如 货币。
  • 默认值为 0.0d。

布尔值

  • 布尔数据类型表示一位信息。
  • 只有两个可能的值:true 和 false。
  • 此数据类型用于跟踪 true/false 的简单标志 条件。
  • 默认值为 false。

字符

  • har 数据类型是单个 16 位 Unicode 字符。
  • 最小值为“\u0000”(或 0)。
  • 最大值为“\uffff”(或 65,535,含 65,535)。
  • Char数据类型用于存储任何字符。

如您所见,上述类型的 none 可以存储您的值,因此您必须使用 BigInteger (example) 或任何其他可以处理此大值的 class。

我认为您超过了 Java 用于 long 类型的有符号 64 位整数中可以存储的最大 long 值,有关 Long 和这些的更多信息在 Java API:http://docs.oracle.com/javase/7/docs/api/java/lang/Long.html

64位有符号整数的最大正数为2^63 -1:9 223 372 036 854 775 807,你的值好像已经达到这个限制,如果有符号整数的最高位是1,那么有符号整数变为负数(有关更多详细信息,请参阅 2 补整数:http://en.wikipedia.org/wiki/Two%27s_complement)。

您需要使用 BigInteger 来获得任意精度的整数 http://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html

public static void main(String[] args)
    {
        Map<Integer, BigDecimal> fibonacciMap = new HashMap<Integer, BigDecimal>();
        fibonacciMap.put(1, BigDecimal.valueOf(1));
        fibonacciMap.put(2, BigDecimal.valueOf(1));
        System.out.println(1 + " : " + fibonacciMap.get(1));
        System.out.println(2 + " : " + fibonacciMap.get(2));

        for(int i=3;i<=300;i++)
        {
            fibonacciMap.put(i, fibonacciMap.get(i-1).add(fibonacciMap.get(i-2)));
            System.out.println(i + " : " + fibonacciMap.get(i));
        }
    }

因为,java 中 long 的最大值是 9223372036854775807。因此,当斐波那契数超过此最大值时,它开始从 -9223372036854775808(最小值)到零到 9223372036854775807(最大值)四舍五入).因此,我们需要使用 BigDecimal 而不是 Long 来避免 -ve 值。

例如:

Fib[92]=7540113804746346429

Fib[91]=4660046610375530309

(BigDecimal)Fib[93]=Fib[91]+Fib[92]=12200160415121876738 大于 Long.MAX_VALUE

(长)Fib[93]= -6246583658587674878

Long.MAX_VALUE = 9223372036854775807

Long.MIN_VALUE = -9223372036854775808

所以, (BigDecimal)Fib[93] = Long.MAX_VALUE - (Long.MIN_VALUE - (Long)Fib[93]) + 1;