Tag Archives: double

Implementing a high performance Money class

by Mikhail Vorontsov

This article will discuss how to efficiently implement a Money class in Java. This article follows Using double/long vs BigDecimal for monetary calculations article published earlier in this blog.

Introduction

As I have written before, we should not use any floating point types for storing monetary values. We should use long instead, keeping the number of smallest currency units in it. Unfortunately, there is a couple of problems:

  • We may still have to communicate with a software storing monetary values in double variables.
  • We may want to multiply it by a non-integer number, like 0.015, or divide it by any type of number, thus getting the non-integer result.

The easy way to deal with arithmetic operations is to use the BigDecimal class for all of them. Unfortunately, BigDecimal will not help you to deal with already incorrect double calculations results. For example, the following code will print 0.7999999999999999:

1
System.out.println( new BigDecimal( 0.7 + 0.1, MathContext.DECIMAL64 ) );
System.out.println( new BigDecimal( 0.7 + 0.1, MathContext.DECIMAL64 ) );

So, we may say that BigDecimal operations will produce the correct result if it had the correct arguments. We can not say the same about double operations.

double operations may end up with the exact result or a result which is one bit off the exact result. This is most likely caused by executing double operations using higher precision on CPU and then rounding the result. All we need to do to get the exact result is to look at these 3 values (result; result plus one bit value, which is also known as ulp; and result minus ulp). One of them would be the correct one. Easy to say, difficult to efficiently implement 🙂

Continue reading

Using double/long vs BigDecimal for monetary calculations

by Mikhail Vorontsov

This article discusses how to perform monetary operations in Java: what is the correct way of using double and what alternatives do we have.

Monetary operations using long/double

The easiest way to represent monetary values in financial environment is to work with the smallest currency units – for example, cents in USA, instead of normal currency unit – dollar in USA. long datatype is rather suitable for this case. Unfortunately, sometimes we have to divide such values or multiply them by decimal point values (for example, calculate how much you have earned on your savings account). This means that while we can still use long for storing cents, we need to multiply/divide using decimal point arithmetic.

Do not use float for any monetary operations unless you absolutely sure. It has too low precision (23 bits).

double calculations are not precise. Even simple one, such as addition and subtraction:

1
System.out.println( "362.2 - 362.6 = " + ( 362.2 - 362.6 ) );
System.out.println( "362.2 - 362.6 = " + ( 362.2 - 362.6 ) );

will print "362.2 - 362.6 = -0.4000000000000341". This means we should:

  1. Avoid working with non-integral values while using double (calculate in the smallest currency units).
  2. Round any multiplication/division results using Math.round/rint/ceil/floor (per your system requirements).

Continue reading