java java中十进制数的总和

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5423545/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 11:03:13  来源:igfitidea点击:

Sum of decimal number in java

javadoubledecimalapproximation

提问by alepuzio

I have a problem for the managemente of decimal number in java (JDK 1.4).

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

I have two doublenumbers firstand second(as output of formatted String). I do a sum between fist and second and I receive a number with more decimal digits!

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

   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
    */

I prefer not growing the threshold value (0.5d) because I'm not safe with similar situation (when I started coding, the specs was talking about 0.1das comparison value). If it's the only solution, the value of 0.9dis safest value for this problem?

我不喜欢增加阈值(0.5d),因为我在类似情况下不安全(当我开始编码时,规范正在谈论0.1d作为比较值)。如果它是唯一的解决方案,那么0.9d的值是这个问题的最安全值吗?

How I can resolve this situation? I thinked that this problem derive by the use of double variables, but with the float I have the same problem.

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

Some idea (having some tested code line, if possible ;))?

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

采纳答案by Peter Lawrey

You can get rounding error, but I don't see it here.

您可能会遇到舍入错误,但我在这里没有看到。

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);
}

prints

印刷

-0.5

There are two ways to handle this more generally. You can define a rounding error such as

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

 private static final double ERROR = 1e-9;

 if(Math.abs(error)<=0.5d + ERROR){

OR use rounding

或使用四舍五入

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

OR use integers with fixed precision

或使用固定精度的整数

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);
}

OR You can use BigDecimal. This is often the preferred solution for many developers, but a last option IMHO. ;)

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

回答by gnomed

This error will depend slightly on your version of Java (and I see you are using a slightly old one). However, regardless of Java version, for best results when you are particularly worried about decimal accuracy in java, you should use the BigDecimalclass for your values.

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

This is what financial applications use for handling currency, and also what many industrial Java applications use when precision is essential.

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

EDIT: I see many valid comments that this solution comes with a slight performance hit (also depends on the number of operations you are doing in the first place). And really, if this is the only single place that you encounter an issue and you dont care about precision after it, then ya, go for a workaround. But if this happens frequently and in more than one place, or if you think you might be expanding your application in the future, I would use the safer BigDecimal.

编辑:我看到许多有效的评论说这个解决方案带来了轻微的性能影响(也取决于你首先执行的操作数量)。真的,如果这是您遇到问题的唯一一个地方,并且您不关心之后的精度,那么您可以寻求解决方法。但是,如果这种情况经常发生并且发生在多个地方,或者如果您认为将来可能会扩展您的应用程序,我会使用更安全的BigDecimal.

回答by lukastymo

I've tested and on my machine everything is correct (tested in java 1.6). If I were you I would test strictfp modifier to method which has above operations:

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

public static strictfp void main(String[] args)

The problem can be connected with java version, OS, CPU you're using

问题可能与你使用的java版本、操作系统、CPU有关

回答by Nodebody

I agree with Peter, I don't see that happening either. However, if it keeps happening to you and if the number of decimals is known and fixed in your usecase anyway, using "int" might be a solution, that's even faster than floating point operations. For the views you would then have to convert to floating points, of course.

我同意彼得的观点,我也没有看到这种情况发生。但是,如果它一直发生在您身上,并且无论如何在您的用例中小数位数是已知的并且是固定的,那么使用“int”可能是一个解决方案,这甚至比浮点运算更快。当然,对于视图,您必须转换为浮点数。

回答by Kurru

Double items store number in powers of 2. It is not possible to accurately represent a lot of numbers in terms of powers of 2 and so you get rounding issues. The same problem when using floats.

双项以 2 的幂存储数字。不可能根据 2 的幂准确表示大量数字,因此会出现四舍五入问题。使用浮动时同样的问题。

If you want to reduce these, use the Decimal type for the numbers, this should prove to be more accurate.

如果你想减少这些,使用小数类型的数字,这应该被证明更准确。

For doubles and floats, you must use the < comparator to check if 2 numbers are close enough to be considered equal.

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

See this for more details -> What is the most effective way for float and double comparison?

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