tags:

views:

1289

answers:

9

Hello 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

+4  A: 

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.

Stefan Kendall
more fundamentally, doubles don't *have* decimal places, since they're stored as binary fractions.
Michael Borgwardt
A: 

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.

quant_dev
Or use BigDecimal, which is one of the reasons BigDecimal exists.
GregS
You still then need to initialize it from string, not from double.
quant_dev
+11  A: 

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();
}
raoulsson
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.
BalusC
@BalusC: Concerning your first comment, I updated it...
raoulsson
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.
leftbrainlogic
A: 

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);
}
Berek Bryan
+1  A: 

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);
Nathan Hughes
A: 

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.

R. Bemrose
Note: pow is a very expensive function. Use it if performance is not an issue.
Peter Lawrey
+4  A: 

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

Esko
A: 

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];
    assert unscaled > Long.MIN_VALUE && unscaled < Long.MAX_VALUE;
    long unscaledLong = (long) (unscaled + (v < 0 ? -0.5 : 0.5));
    return (double) unscaledLong / TENS[precision];
}

Delete the assert'ions to taste. ;)

Peter Lawrey
A: 

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 ;
}
Syed Mustaffa