1

我只是想了解在使用 java 时如何计算各种值。我首先学习了 BigDecimal 类以及如何使用它进行高精度计算。我理解以下概念:

    BigDecimal xx = BigDecimal.valueOf(0.1);
    BigDecimal yy = BigDecimal.valueOf(0.2);


    System.out.printf("Number is: %s", xx.add(yy,new MathContext(30, RoundingMode.HALF_DOWN)).toString());

我得到了我期望的 0.3 的结果。我接下来尝试并仍然坚持的是在计算后显示非常长的十进制值。我有2个例子。

    BigDecimal xx = BigDecimal.valueOf(0.111111111111111111111111111111);
    BigDecimal yy = BigDecimal.valueOf(0.001111111111111111111111111111);


    System.out.printf("Number is: %s", xx.add(yy,new MathContext(30, RoundingMode.HALF_DOWN)).toString());

结果应该是 0.112222...222,但结果是 0.1122222222222222111。

第二个例子是使用减法而不是加法。答案应该是 0.11,但我最终得到的是 0.1099999999999999889。

我想我的问题分为两部分。第一部分包括我如何修复上述示例以获得正确答案,第二部分更笼统一些。我最终想要运行一些我想要非常高精度的物理计算,比如小数点后 20-30 位。我怎样才能执行我的计算,以便我保留我的答案并用小的舍入问题和/或截断来显示它们?

4

3 回答 3

5

BigDecimal xx = BigDecimal.valueOf(0.111111111111111111111111111111);

您在double此处使用文字,其精度有限且容易出现舍入错误。

一直使用小数。

BigDecimal xx = new BigDecimal("0.11111111111111111111111111111");

当然,如果长数字不是硬编码到程序中的东西,而是浮点计算的结果,那么你已经有了舍入误差,并且必须忍受它。转换为 BigDecimal 无法再解决此问题。

如何执行我的计算,以便我保留我的答案并以小的舍入问题和/或截断显示它们?

除了打印时四舍五入,您无能为力。 Printf 具有类似“%.12d”的格式字符串。

于 2013-05-04T06:10:29.173 回答
2

我想我的问题分为两部分。第一部分包括我如何修复上述示例以获得正确答案

使用接受 String 的构造函数

BigDecimal xx = new BigDecimal("0.111111111111111111111111111111");
BigDecimal yy = new BigDecimal("0.001111111111111111111111111111");

第二部分更笼统一些。我最终想要运行一些我想要非常高精度的物理计算,比如小数点后 20-30 位。

您应该是 BigDecimal 可以慢 100 倍,并且在现实世界中您可以测量到 15 位精度的东西很少。我会重新考虑什么“物理”问题真正需要 20-30 位数的准确度。

于 2013-05-04T06:36:58.827 回答
0

这是您问题的难点:

我最终想要运行一些我想要非常高精度的物理计算,比如小数点后 20-30 位。如何执行我的计算,以便我保留我的答案并以小的舍入问题和/或截断显示它们?

对此没有简单的答案。这实际上取决于“物理计算”的性质。一些计算相对不易出错;即舍入误差对最终答案的影响不大。在其他情况下(例如混沌系统),错误会迅速累积并最终淹没答案。

您如何进行计算也很重要。例如,有一种基本的统计计算涉及计算两个“平方和”(或类似的东西)之间的差异。SoS 值通常非常大,但差异很小。如果您以错误的方式进行计算,您会得到一个不精确的差值。如何进行计算的另一个问题是矩阵求逆。

值得一提的是,有一个数学分支处理数值计算和准确性。它被称为数值分析。在“过去的美好时光”中,它是计算机科学课程的一部分。

于 2013-05-04T07:04:57.077 回答