# Computing @ 40's

## Trying to overcome the obsolescence # Java float and double primitive types are evil. Don’t use them.

Today I am writing a short article to show people why I decided some time ago to not to use Java float or double primitive types in any case.

When you start programming Java, one of the firsts lessons is to show java primitive types like int, short, long, byte, etc… All these are used to store integers in different range of values available. For floating point numbers, exists two types: float and double types.

But usually people is not aware that when using float or doubles they are entering to a twilight zone that can bring them a lot of headaches.

To see the reason let’s look a simple example. Take this code and run it on Eclipse or Netbeans. It’s a simple Java class with a main procedure.

```package com.booreg.tests;

public class ILoveYouMySillyFloatMain
{
public static void testWithFloats()
{
System.out.println("testWithFloats\n");
float a = 0.1f;
float b = 0.1f;
float c = 0.1f;

float d = a + b + c;
float e = d * 3;
float f = d * 100000;

System.out.println("a + b + c = d = " + d);
System.out.println("e = " + e);
System.out.println("f = " + f);
System.out.println("");
}

public static  void testWithDoubles()
{
System.out.println("testWithDoubles\n");

double a = 0.1;
double b = 0.1;
double c = 0.1;

double d = a + b + c;
double e = d * 3;
double f = d * 100000;

System.out.println("a + b + c = d = " + d);
System.out.println("e = " + e);
System.out.println("f = " + f);
System.out.println("");
}

public static void main(String[] args)
{
testWithFloats();
testWithDoubles();
}
}
```

As you see is a really simple program doing three simple operations based on three variables with the same value: 0.1.  When running this example you would expect an output like this:

```testWithFloats

a + b + c = d = 0.3
e = 0.9
f = 30000

testWithDoubles

a + b + c = d = 0.3
e = 0.9
f = 30000
```

So, what you expect is to have the same results for float or double tests, and results of 0.3, 0.9 and 30000.

But, when you run it you see a result like this !!!

```testWithFloats

a + b + c = d = 0.3
e = 0.90000004
f = 30000.002

testWithDoubles

a + b + c = d = 0.30000000000000004
e = 0.9000000000000001

f = 30000.000000000004
```

Incredible ! Amazing ! The two tests return different values and almost none of them are correct !!!!

What happened here ? It’s me or my eyes ? Should I visit the doctor ? No, the problem comes because of how Java stores floating point values on memory. They use binary representation of that values, and this means that implicitly that values are loosing precission. That is. In binary format is not always possible to store real number values with total precission.

I wonder how it’s possible for Java designers to introduce a java type that implicitly can generate errors. Imagine our bank using Java programs filled with floats and doubles everywhere. Not really serious in my opinion.

### So, is there any solution ?

Yes, of course, and is relatively simple, although makes the code not so clean as I would like. The solution is to not to use float or double but to use java class BigDecimal instead. Use always BigDecimal. Always. Don’t use any second to think if you really need them or not. Use it and all the operations will have exact results.

So, take the example above and wtite the BigDecimal version, like this.

```package com.booreg.tests;

import java.math.BigDecimal;

public class ILoveYouMySillyFloatMain
{
public static void testWithFloats()
{
System.out.println("testWithFloats\n");

float a = 0.1f;
float b = 0.1f;
float c = 0.1f;

float d = a + b + c;
float e = d * 3;
float f = d * 100000;

System.out.println("a + b + c = d = " + d);
System.out.println("e = " + e);
System.out.println("f = " + f);
System.out.println("");
}

public static void testWithDoubles()
{
System.out.println("testWithDoubles\n");

double a = 0.1;
double b = 0.1;
double c = 0.1;

double d = a + b + c;
double e = d * 3;
double f = d * 100000;

System.out.println("a + b + c = d = " + d);
System.out.println("e = " + e);
System.out.println("f = " + f);
System.out.println("");
}

public static  void testWithBigDecimals()
{
System.out.println("testWithBigDecimals\n");

BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.1");
BigDecimal c = new BigDecimal("0.1");

BigDecimal e = d.multiply(new BigDecimal("3"));
BigDecimal f = d.multiply(new BigDecimal("100000"));

System.out.println("a + b + c = d = " + d);
System.out.println("e = " + e);
System.out.println("f = " + f);
System.out.println(");
}

public static void main(String[] args)
{
testWithFloats();
testWithDoubles();
testWithBigDecimals();
}
}
```

Notice that BigDecimal variables are declared using strings values instead of a literal value. If you initialize the BigDecimal variable a with

` BigDecimal a = new BigDecimal(0.1); `

you will reproduce the floating-point problem again, because the compiler makes an implicit conversion of 0.1 value to a double value, loosing the precission that we want to keep.

Is a little bit harder to work with BigDecimal. For example you can initialize a zero value using this sentence: BigDecimal a = BigDecimal.ZERO; It’s not so polite that when using float or double, but you will not have surprises later.

There are multiple Internet entries talking about this. Making a little search in Google, it’s easy to find more information. Probably you will find them before this little and modest blog entry. For example take a look at http://stackoverflow.com/tags/floating-point/info or at http://floating-point-gui.de/

They explain better some things about binary representations of floating point numbers.

But everything can be sumarized with only one idea: never, never, never use float or double java primitive types. Use BigDecimal instead.

Cardedeu, September 30th, 2013

### 10 thoughts on “Java float and double primitive types are evil. Don’t use them.”

1. Hmm as the Big Decimal is an Object, all operations will be slower on them. There are application areas such as a signal processing for example where many-thousands-items-arrays are repeatedly processed in real time. The performance impact there could be fatal. So in cases where the performance rules I would suggest using the primitives. In cases where the accuracy rules, use the BigDecimal.

• Well, this is the main reasoning of people defending the use of double and float types. You are right that the performance is significantly slower with BigDecimal than with float or double types. But in case that your application doesn’t need it, I wouldn’t have any doubt of using BigDecimal. The title of this article was intentionally provocative to make people thinking about using that primitives types without worrying the lost of precision.

Many thanks for your comment. I appreciate all of them.

2. The Java floating point types double and float store their values in the scientific IEEE format. Exactly the same format common CPUs (Intel, AMD, etc.) use internally. It is optimized for performance in scientific calculations.
However, most Java programmers write business applications. In the business area precision usually is most important, especially when it comes to price information etc.. So for business applications use the slow BigDecimal, for performance critical scientific calculations, use double and float. The difference in performance is big (just a guess: about factor ~10 up to 100), however in a business application this is not noticable as the calculations are not complex in that area.
So you are right: in a business application, use BigDecimal. If performance is not an issue, use BigDecimal. Use double and float only if performance is critical (e.g. compression algorithms, 3D graphics etc.).

• Hi Jens.

I wanted to answer you before, sorry for this long delay but some circumstances have made me answer late.

I agree with you. When I wrote this article I was thinking specially in bussiness applications, so that’s why the title was intentionally provocative, just to emphasize the devil side of float and double types in that kind of applications. Even with that, having in mind the power of current CPUs, I think that the question of performance should be very well explained to justify using that primitive types.

3. This post is unfortunately very wrong.

The problem with floating point numbers with fixed precision (float, double) is that they do not represent real numbers, but only a very small subset of rational numbers. BigDecimal is different only in that it has arbitrary precision (arbitrary, but still finite), and thus it cannot represent all real numbers. BigDecimals is unable to currently count 1/3 + 1/3 + 1/3:

@Test
public void testBigDecimal() {
final int div = 3;
final int precision = 100;

BigDecimal part = BigDecimal.ONE.divide(new BigDecimal(3), precision, BigDecimal.ROUND_HALF_DOWN);
BigDecimal sum = BigDecimal.ZERO;
for (int i = 0; i < div; ++i) {
}

assertEquals(sum, BigDecimal.ONE);
}

The result is:

java.lang.AssertionError: expected  but found [0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999]
Expected :1
Actual :0.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999

No matter what value of precision you pick, you will never have the correct value.

My recommendation is: for mutliplication, addition and substraction, BigDecimal is precise (unlike float & double), but when it comes to division or other functions (roots, goniometric functions …), absolute precision is not achievable and you will have to do some rounding.

• Hi Michal.

Thanks for your comment. All of them are welcome, even if people don’t agree with what I was saying.

As you see in this article I was doing simple operations, like addition, substraction and multiplication, and they gave me unexpected results. Of course both BigDecimal and primitive types will have problems when working with some divisions. But this post, and it’s title, was intentionally provocative, to make people think that many times they will find situations where the primitive types will not suite the expected functionality. Imagine if a bank makes 0.1 + 0.1 + 0.1 operations frequently. They will fall in bankrupt in a few months, or they will loose a lot of customers if they don’t care about it.

Even making simple operations like converting a String to a decimal point number can cause a lot of problems. In general we think that operations with numbers are exactly precise for simple operations (although we know that this is not true for operations like the examples you gave), so, we expect exact result from exact operations. If we fall down in the trap of thinking that java float and double types are good for everything we will have a lot of problems in our programs.

4. Thanks for sharing this. I learnt this the hard way though. I failed an interview because I used the float data type. I never knew this until after the interview. BigDecimal gave me the right result but it was too late. I still wonder why I never noticed this since I started using java.

5. Scientific computation can not afford to use BigDecimal in intensive computation. It’s a complete no-go.

Numerical analysts are well aware of the problems of limited precision, and are equally well versed in handling those problems.

6. ok.. it is good to read the comments to get an understanding of pros and cons