java中十进制数的总和

我在java(JDK 1.4)中管理十进制数的问题。

我有两个数字第一第二 (作为格式化字符串的输出)。 我在第一个和第二个之间做了一个总和,我收到一个带有更多十进制数字的数字!

final double first=198.4;//value extract by unmodifiable format method final double second=44701.2;//value extract by unmodifiable format method final double firstDifference= first+second; //I receive 44899.598 instead of 44899.6 final double calculatedDifference=44900.1; // comparison value for the flow final double error=firstDifference-calculatedDifference;// I receive -0.50390605 instead 0.5 if(Math.abs(error)<=0.5d)){ //I must enter in this branch but the error not allows the correct flow!!! } /*** * the flow of program is uncorrect and there's a very visible bug in business view */ 

我不想增加阈值( 0.5d ),因为我在类似情况下不安全(当我开始编码时,规格是将0.1d作为比较值)。 如果这是唯一的解决方案, 0.9d的值对于这个问题是最安全的值吗?

我该如何解决这种情况? 我认为这个问题是通过使用double变量得出的,但是浮点数我有同样的问题。

一些想法(如果可能的话,有一些经过测试的代码行);)?

您可以获得舍入错误,但我在这里看不到它。

 final double first=198.4;//value extract by unmodifiable format method final double second=44701.2;//value extract by unmodifiable format method final double firstDifference= first+second; //I receive 44899.6 final double calculatedDifference=44900.1; // comparison value for the flow final double error=firstDifference-calculatedDifference;// I receive -0.5 if(Math.abs(error)<=0.5d){ // this branch is entered. System.out.println(error); } 

版画

 -0.5 

有两种方法可以更普遍地处理这个问题。 您可以定义舍入错误,例如

  private static final double ERROR = 1e-9; if(Math.abs(error)<=0.5d + ERROR){ 

或使用四舍五入

 final double firstDifference= round(first+second, 1); // call a function to round to one decimal place. 

或者使用具有固定精度的整数

 final int first=1984;// 198.4 * 10 final int second=447012; // 44701.2 * 10 final int firstDifference= first+second; //I receive 448996 final int calculatedDifference=449001; // comparison value for the flow final int error=firstDifference-calculatedDifference;// I receive -5 if(Math.abs(error)<=5){ // this branch is entered. System.out.println(error); } 

或者您可以使用BigDecimal。 这通常是许多开发人员的首选解决方案,但最后一个选项是恕我直言。 ;)

此错误将略微取决于您的Java版本(我发现您使用的是稍微旧的版本)。 但是,无论Java版本如何,为了在您特别担心java中的小数精度时获得最佳结果,您应该使用BigDecimal类作为值。

这是金融应用程序用于处理货币的原因,也是许多工业Java应用程序在精度至关重要时使用的内容。

编辑:我看到许多有效的评论,这个解决方案带来轻微的性能影响(也取决于你在一开始就做的操作数)。 实际上,如果这是你遇到问题的唯一一个地方,你不关心它之后的精度,那么,你去找一个解决方法。 但是,如果这种情况频繁发生并且不止一次发生,或者您认为将来可能会扩展您的应用程序,我会使用更安全的BigDecimal

双项目以2的幂存储数字。不能以2的幂来准确地表示许多数字,因此您会得到四舍五入的问题。 使用浮动时同样的问题。

如果你想减少这些,请使用数字的十进制类型,这应该被certificate更准确。

对于双精度浮点数和浮点数,必须使用<比较器来检查2个数字是否足够接近以使其相等。

有关详细信息,请参阅此内容 – > 浮动和双重比较的最有效方法是什么?

我已经在我的机器上测试了一切都是正确的(在java 1.6中测试过)。 如果我是你,我会测试strictfp修饰符到具有上述操作的方法:

 public static strictfp void main(String[] args) 

问题可以与您正在使用的java版本,操作系统,CPU相关联

我同意彼得,我也不认为这种情况发生了。 但是,如果它一直发生在您身上并且如果已知并在您的用例中修复小数位数,则使用“int”可能是一种解决方案,这甚至比浮点运算更快。 对于视图,您当然必须转换为浮点数。