【问题标题】:Loss of precision multiplying large longs乘以大多头的精度损失
【发布时间】:2023-03-09 17:38:01
【问题描述】:

我正在研究一个本质上是斐波那契数列的问题陈述:

给定两个初始值作为输入,计算 term x = (term x-1)^2 + (term x-2)

所以,给定输入 0 1 5,我们要计算序列的第 5 项,按以下方式完成:

第 3 项 = (第 2 项)^2+(第 1 项) = 1^2 + 0 = 1

第 4 项 = (第 3 项)^3+(第 2 项) = 1^1 + 1 = 2

第 5 项 = 2^2+1 = 5

等等。

当我尝试计算一个较大的值时,比如第 10 个,我的问题就出现了。使用 long 作为我的数据类型,我在第 10 个值处精确丢失了精度。预期/正确的值是`84266613096281243382112,但我明白了..

0 1 10
Term number 3 has value 1
Term number 4 has value 2
Term number 5 has value 5
Term number 6 has value 27
Term number 7 has value 734
Term number 8 has value 538783
Term number 9 has value 290287121823
Term number 10 has value 1886167576011600224

使用double作为我的数据类型做同样的问题,而不是给我正确的答案,但不是我需要的格式(这是用于自动化测试用例)。

0 1 10
Term number 3 has value 1.0
Term number 4 has value 2.0
Term number 5 has value 5.0
Term number 6 has value 27.0
Term number 7 has value 734.0
Term number 8 has value 538783.0
Term number 9 has value 2.90287121823E11
Term number 10 has value 8.426661309628124E22

为什么我会遇到这种长时间的精度损失,我该如何防止它/获得我想要的输出?

【问题讨论】:

标签: java double long-integer


【解决方案1】:

尝试使用 BigInteger 类,它可以工作:

import java.math.BigInteger;

public class Test {

    public static void main(String[] args) {
        BigInteger x1, x2, x3;

        x1 = new BigInteger("0");
        x2 = new BigInteger("1");

        for (int i = 3; i <= 10; i++){
            x3 = x2.multiply(x2).add(x1);
            System.out.println(i + ":" + x3);
            x1 = x2;
            x2 = x3;
        }
    }

}

【讨论】:

    【解决方案2】:

    那是因为long's max value is 2^63-1(或 9.223372e+18)。你简直不能再高了。

    如果double 对您的应用程序来说具有足够的精度,您可以根据规范对其进行格式化,例如DecimalFormat

    如果double 不够精确,您可以使用BigInteger 查看。但这会带来更高的性能成本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-13
      • 1970-01-01
      • 2015-04-26
      • 2013-07-14
      相关资源
      最近更新 更多