如何避免使用双精度取整错误?

时间:2019-05-03 23:29:34

标签: java math double rounding

我正在使用Math.sin在Java中以3位小数精度计算三角函数。但是,当我计算应该导致整数的值时,我得到的是1.0000000002而不是1。

我尝试使用

 System.out.printf(Locale.ROOT, "%.3f ", v);

确实解决了 1.000000002 变成 1.000的问题。

但是,当我计算得出应为 0 的数字并得到 -1.8369701987210297E-16 并使用

时,
  System.out.printf(Locale.ROOT, "%.3f ", v);

在我需要为0.000时打印出-0.000。

关于如何消除负号的任何想法?

2 个答案:

答案 0 :(得分:3)

让我们以此开始:

  

如何避免使用双精度取整错误?

基本上,您不能。它们是使用浮点类型进行数值计算所固有的。相信我...或抽出时间阅读本文:

在这种情况下,另一件事是三角函数是通过以有限精度(即浮点)算术计算无限级数的有限步数来实现的。 Math类的javadoc在数学函数的准确性上留下了一些“摆动空间”。值得阅读javadocs以了解 expected 的错误范围。

最后,例如,如果您正在计算 sinπ/ 2 ,则需要考虑π/ 2 的表示形式的准确性。


所以您真正要问的是如何处理不可避免的舍入错误。

在这种情况下,您要问的是如何使其看起来像程序的用户,就好像没有舍入错误一样。有两种解决方法:

  • 别管它!出现四舍五入错误,因此我们不应该对用户撒谎。最好教育他们。 (老实说,这是高中数学,甚至“尖头的老板”也应该理解算术是不精确的。)

    printf这样的例程做得很好。在这种情况下显示的-0.000实际上是一个真实的答案。这意味着计算出的答案四舍五入到零到3个小数位,但实际上是负数。对于高中数学的人来说,这实际上并不难理解。如果你解释的话。

  • 谎言。假装。放入一些特殊情况的代码,以将-0.0005和零之间的数字显式转换为恰好为零。注释中建议的代码

      System.out.printf(Locale.ROOT, "%.3f ", Math.round(v * 1000d) / 1000d);
    

    是完成这项工作的另一种方法。但是这样做的风险是,在某些情况下说谎可能很危险。另一方面,您可以说真正的错误问题是将数字显示为小数点后3位。

答案 1 :(得分:0)

根据您需要的精度,您可以乘以X并除以X,其中X是X=10^y,而y是浮点精度。