Are there any functions for truncating a double in java?
Asked Answered
C

12

24

Is there a Java Library function which can be used to truncate a number to an arbitrary number of decimal places? For Example.

SomeLibrary.truncate(1.575, 2) = 1.57

Thanks

Coadjutress answered 29/12, 2009 at 20:35 Comment(1)
possible duplicate of Round a double to 2 significant figures after decimal pointOilla
H
31

Try setScale of BigDecimal like so:

public static double round(double d, int decimalPlace) {
    BigDecimal bd = new BigDecimal(d);
    bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
    return bd.doubleValue();
}
Hyperthermia answered 29/12, 2009 at 20:38 Comment(4)
2 comments: the BigDecimal has already a constructor taking a Double. The OP also doesn't seem want to round it half up, but just to truncate (floor) it.Hine
Actually, BalusC is right, I want to truncate the value however, your answer set me off in the right direction so I'm accepting it.Coadjutress
you need to set the RoundingMode to BigDecimal.ROUND_DOWN instead of ROUND_HALF_UP to really truncate a valueTerrorism
improved version of this #7747969 with positive and negative value and not roundingOutpost
R
15

Incredible no one brought this up yet, Java API has had DecimalFormat for ages now for this exact purpose.

Railway answered 29/12, 2009 at 21:24 Comment(2)
Concretely for the given example the code would look something like this: final DecimalFormat df = new DecimalFormat(); df.setMaximumFractionDigits(2); df.format(1.575); The last expression returns a String which has to be converted back to a double.Rayon
This will do round, i think the question to truncate not round.Outpost
B
6

For most numbers, you won't be able to get an exact representation of xxx.yyyy unless you use a decimal class with guaranteed accuracy, such as BigDecimal.

Buskin answered 29/12, 2009 at 20:37 Comment(1)
more fundamentally, doubles don't have decimal places, since they're stored as binary fractions.Facer
A
6

There's one in commons-math. Check out http://commons.apache.org/math/apidocs/org/apache/commons/math/util/MathUtils.html:

public static double round(double x,
                           int scale)

It's implemented using BigDecimal, and is overloaded to allow specifying a rounding method, so you can use it to truncate, like this:

org.apache.commons.math.util.MathUtils.round(1.575, 2, 
    java.math.BigDecimal.ROUND_DOWN);

Update:

In the last version (Math3), this method is in the class Precision. org.apache.commons.math3.util.Precision.round(double x, int scale, int roundingMethod)

Abeu answered 29/12, 2009 at 20:46 Comment(0)
B
5

Simply remove the fractional portion:

public double trunk(double value){
    return value - value % 1;
}
Butterfield answered 11/11, 2013 at 1:24 Comment(0)
I
2

here is a short implementation which is many times faster than using BigDecimal or Math.pow

private static long TENS[] = new long[19];
static {
    TENS[0] = 1;
    for (int i = 1; i < TENS.length; i++) TENS[i] = 10 * TENS[i - 1];
}

public static double round(double v, int precision) {
    assert precision >= 0 && precision < TENS.length;
    double unscaled = v * TENS[precision];
    if(unscaled < Long.MIN_VALUE || unscaled > Long.MAX_VALUE) 
       return v;
    long unscaledLong = (long) (unscaled + (v < 0 ? -0.5 : 0.5));
    return (double) unscaledLong / TENS[precision];
}

Delete the assert'ions to taste. ;)

Inhibit answered 29/12, 2009 at 21:49 Comment(6)
The only problem I see with this is that you are multiplying parameter v by (potentially) several powers of 10, which can cause an overflow. Sure, double max value is around 10^308 so most people won't notice this, however it is possible, which is surprising behaviour (you don't expect a rounding function to have an overflow when submitting a valid value).Pushed
Just noticed the method will fail as soon as unscaled value will exceed long type, which is way sooner. This could be pretty fast even if parameter v is small if enough precision is requested.Pushed
@UMad Ok, changed the check which should handle both cases.Inhibit
round(9.625, 2) returns 9.63 which is wrong as per the question. the answer should be 9.62Outpost
@mani good point, if you just want to truncate you can drop the + 0.5Inhibit
@PeterLawrey dropping +0.5 will not work for round(9.62,2) to 9.61 . the problem is double doesn't has actual decimal point you have to use the BigDecimal or should add extra conditionsOutpost
C
2

Use this simple function

double truncateDouble(double number, int numDigits) {
    double result = number;
    String arg = "" + number;
    int idx = arg.indexOf('.');
    if (idx!=-1) {
        if (arg.length() > idx+numDigits) {
            arg = arg.substring(0,idx+numDigits+1);
            result  = Double.parseDouble(arg);
        }
    }
    return result ;
}
Cruikshank answered 26/8, 2010 at 6:31 Comment(0)
V
2

I just want to add to ubuntudroid's solution. I tried it and it wouldn't round down, so I had to add

df.setRoundingMode(RoundingMode.FLOOR);

for it to work.

Victualler answered 10/10, 2012 at 0:45 Comment(0)
M
0

To do it 100% reliably, you'd have to pass the argument as string, not as floating-point number. When given as string, the code is easy to write. The reason for this is that

double x = 1.1;

does not mean that x will actually evaluate to 1.1, only to the closest exactly representable number.

Mayor answered 29/12, 2009 at 20:37 Comment(2)
Or use BigDecimal, which is one of the reasons BigDecimal exists.Ronnieronny
You still then need to initialize it from string, not from double.Mayor
I
0

Actually, this sort of thing is easy to write:

public static double truncate(double value, int places) {
    double multiplier = Math.pow(10, places);
    return Math.floor(multiplier * value) / multiplier;
}

Note that it's Math.floor, because Math.round wouldn't be truncating.

Oh, and this returns a double, because that's what most functions in the Math class return (like Math.pow and Math.floor).

Caveat: Doubles suck for accuracy. One of the BigDecimal solutions should be considered first.

Impressible answered 29/12, 2009 at 20:48 Comment(4)
Note: pow is a very expensive function. Use it if performance is not an issue.Inhibit
I like this solution for simplicity and clarity.Osric
@Outpost (well, applies to what EJP said too): I'll note that the Caveat is there for a reason.Impressible
@Impressible The objective is to truncate a double to an arbitrary number of decimal places, and any solution should do exactly that. This code does not and cannot do it, not because of 'accuracy' but because binary fractions and decimal fractions are incommensurable.Backwardation
S
0

Have you ever tried?

int converted = (int) (someDoubleValue);

Example:

double d = 2.55d;
int i = (int) d; // 2
Smegma answered 10/6 at 0:58 Comment(2)
Please be more explicit, what does it do? How is this different from the other answers? By giving context and details you will improve the quality of your answerBlob
@mozway, a simple and straight way to get rid of the decimal part was asked. Example given.Smegma
F
-1

created a method to do it.

public double roundDouble(double d, int places) {
    return Math.round(d * Math.pow(10, (double) places)) / Math.pow(10, (double)places);
}
Fungus answered 29/12, 2009 at 20:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.