Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we’ll look at a range of options in Java for truncating a double to two decimal places. We’ll see methods that leave us with a String and options for returning Numbers as well.

2. Using Math.floor() and Math.ceil() Rounding

The first method we’ll examine is using the Math class to remove extra decimal places. To truncate a positive number to two decimal places, we first multiply our double by 100, moving all the numbers we want to keep in front of the decimal place. Next, we use Math.floor() to round down, removing everything after the decimal place. Finally, we divide by 100 to undo the previous multiplication:

@Test
void givenADouble_whenUsingMath_truncateToTwoDecimalPlaces(){
    double positive = 1.55555555;
    double truncated = Math.floor(positive * 100) / 100;
    assertEquals("1.55", String.valueOf(truncated));

    double negative = -1.55555555;
    double negativeTruncated = Math.ceil(negative * 100) / 100;
    assertEquals("-1.55", String.valueOf(negativeTruncated));
}

The process is almost identical for a negative number, but instead of Math.floor(), we use Math.ceil() to round up. We could’ve added extra code to detect if the double is negative or positive and automatically use the correct method if we wanted.

For removing more or less decimal places, we’d add or remove zeros to the number we multiplied and divided by. For example, to keep three decimal places, we’d multiply and divide by 1000. This method is useful if we need to keep our double as a double and not end up converting it to a String.

3. Using String.format()

Let’s move on to options that are designed for display purposes rather than calculations. We’ll get a String back from these methods but can always convert the result back to a double if needed. The String.format() method takes two arguments. Firstly, the format we want to apply, and secondly, the arguments referenced by the format. To truncate to two decimal places, we’ll use the format String “%.2f”:

@Test
void givenADouble_whenUsingStringFormat_truncateToTwoDecimalPlaces() {
    double positive = 1.55555555;
    String truncated = String.format("%.2f", positive);
    assertEquals("1.56", truncated);

    double negative = -1.55555555;
    String negativeTruncated = String.format("%.2f", negative);
    assertEquals("-1.56", negativeTruncated);
}

 

The ‘f’ at the end of our format String instructs the formatter to produce a decimal format, and the ‘.2’ means we want two digits after the decimal place. We could adjust this to truncate to the amount of decimal places required. We can see in the test that the result has, in fact, rounded up rather than truncating, so depending on our requirements, this may not be suitable.

4. Creating a String Using NumberFormat

NumberFormat is an abstract class designed to let us format any number. Because it’s an abstract class, we need to use getNumberInstance() first to receive an object we can use. Note that this will use our default locale unless we instruct it to do otherwise. We can follow that by using setMaximumFractionDigits() to say how many decimal places we want. Finally, because we want to truncate rather than round, we call setRoundingMode() with the argument RoundingMode.DOWN:

@Test
public void givenADouble_whenUsingNumberFormat_truncateToTwoDecimalPlaces(){
    NumberFormat nf = NumberFormat.getNumberInstance();
    nf.setMaximumFractionDigits(2);
    nf.setRoundingMode(RoundingMode.DOWN);

    double value = 1.55555555;
    String truncated = nf.format(value);
    assertEquals("1.55", truncated);

    double negativeValue = -1.55555555;
    String negativeTruncated = nf.format(negativeValue);
    assertEquals("-1.55", negativeTruncated);
}

With our NumberFormat setup, it’s then as easy as calling format() with our double. In our test above, we can see that it performs equally well with positive and negative numbers.

5. Creating a String Using DecimalFormat

DecimalFormat is a subclass of NumberFormat specifically designed for decimals. It’s a concrete class, so we can go ahead and make an instance of it directly, passing in our desired pattern to the constructor. We’ll pass in “#.##.” here, the number of hashes after the decimal places indicates how many to keep:

@Test
public void givenADouble_whenUsingDecimalFormat_truncateToTwoDecimalPlaces(){
    DecimalFormat df = new DecimalFormat("#.##");
    df.setRoundingMode(RoundingMode.DOWN);

    double value = 1.55555555;
    String truncated = df.format(value);
    assertEquals("1.55", truncated);

    double negativeValue = -1.55555555;
    String negativeTruncated = df.format(negativeValue);
    assertEquals("-1.55", negativeTruncated);
}

Like with NumberFormat earlier, we’ve specified the use of RoundingMode.DOWN. We see again that this solution handles positive and negative numbers well, making it useful.

6. Optimum Accuracy With BigDecimal

Java’s BigDecimal class is best suited to dealing with truncating decimal places directly while keeping the result as a number we can work with. If it’s possible to use this instead of a double, it may be the best option. We can create a BigInteger by passing our double value into the constructor and directly telling it to keep two decimal places by rounding down at the same time:

@Test
void givenADouble_whenUsingBigDecimal_truncateToTwoDecimalPlaces(){
    BigDecimal positive = new BigDecimal(2.555555).setScale(2, RoundingMode.DOWN);
    BigDecimal negative = new BigDecimal(-2.555555).setScale(2, RoundingMode.DOWN);
    assertEquals("2.55", positive.toString());
    assertEquals("-2.55", negative.toString());
}

We’ve cast the results to Strings for the purposes of this test to make it visually clear what the result is. However, we could have gone on to perform further calculations using the truncated outputs if we wanted to.

7. Conclusion

We’ve looked at five different ways we can truncate a double in Java. We’ve seen that String.format(), NumberFormat, and DecimalFormat are usable if we’re creating something for display purposes as they output Strings. Of course, we can always use Double.parseDouble() to convert our Strings back to doubles. Alternatively, we can either use the Math class or BigDecimal to keep our truncated values as numbers for further calculations.

As always, the full code for the examples is available over on GitHub.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.