我正在使用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。
关于如何消除负号的任何想法?
答案 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是浮点精度。