Sum of decimal in java

I have a problem for decimal control in java (JDK 1.4).

I have two double numbers first and second (as the output of a formatted string). I make a sum between a fist and a second, and I get a number with more decimal digits!

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 a very visible bug in business view */ 

I prefer not to increase the threshold value ( 0.5d ) because I'm not sure about this situation (when I started coding, the specifications spoke of 0.1d as a comparative value). If this is the only solution, is 0.9d the safest for this problem?

How can I solve this situation? I thought this problem is due to the use of double variables, but with the float I have the same problem.

Some idea (with some code line checking, if possible;))?

+4
source share
5 answers

You may get a rounding error, but I do not 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 deal with 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 fixed-precision integers

 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 the latest version is IMHO.;)

+3
source

This error will be slightly dependent on your version of Java (and I see that you are using a bit old). However, regardless of the version of Java, for best results, when you are particularly concerned about decimal precision in java, you should use the BigDecimal class for your values.

This is what financial applications use for currency processing, and also what many industrial Java applications use when accuracy is important.

EDIT: I see a lot of valid comments that this solution comes with little success (also depends on the number of operations you do first). Indeed, if this is the only place in which you encounter a problem, and after that you do not care about accuracy, then you go around the workaround. But if this happens frequently and in more than one place, or if you think you can expand your application in the future, I would use a more secure BigDecimal .

+3
source

Double positions keep the number in force 2. It is impossible to accurately represent the number of numbers in terms of authority 2, and therefore you get rounding problems. Same problem when using float.

If you want to reduce them, use the decimal type for numbers, this should be more accurate.

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

See this for more details β†’ What is the most efficient way for floating and double comparing?

0
source

I tested and everything is correct on my machine (tested in java 1.6). If I were you, I would test the strictfp modifier for a method that has the following operations:

 public static strictfp void main(String[] args) 

The problem may be related to the version of java, OS, the processor you are using

0
source

I agree with Peter, I don’t see this either. However, if this continues with you, and if the number of decimal places is known and corrected in your usecase, using "int" may be a solution that is even faster than floating point operations. Of course, for representations you will need to convert to floating points.

0
source

Source: https://habr.com/ru/post/1345143/


All Articles