Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Truncating float to the two first non-zero decimal digits

I want to truncate floating point numbers in Java up to the two first non-zero decimal digits. For example, 0.000134 to 0.00013, or 11.00401 to 11.0040.

The only solution I can think of is to strip the integral part, and multiply by 10 until I get a number bigger or equal to 10. Then truncate the original float up to number of multiplications decimal digits.

But I might have to do this operation often, so I'm looking for a faster solution.

My test code:

public static String truncateTo2NonZero(double f) {
    int integral = (int)f;
    double decimal = f - integral;
    int digits = 0;

    while (decimal < 10) {
        decimal *= 10;
        digits++;
    }

    double ret = (int)decimal / Math.pow(10, digits);
    ret += integral;

    return Double.toString(ret);
}

public static void main(String args[]) {
    final int TESTS = 1000000;
    double[] floats = new double[TESTS];

    Random random = new Random();
    for (int i = 0; i < TESTS; ++i) {
        int zeros = random.nextInt(6) + 3; // divide by 10^zeros
        double digits = random.nextInt(100) + 100; // 3 last digits
        floats[i] = digits / Math.pow(10,zeros) + random.nextInt(20) + 1;
    }

    long startTime = System.nanoTime();
    for (int i = 0; i < TESTS; ++i)
        truncateTo2NonZero(floats[i]);
    long endTime = System.nanoTime();

    long duration = endTime - startTime;
    System.out.println(duration / 1000000); // in milliseconds
}

I'm using Windows 7 Home Premium 64-bit. Output of java -version:

java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
like image 741
devil0150 Avatar asked Mar 02 '26 20:03

devil0150


1 Answers

When you say you want to "truncate" this sounds like a display format. That being said floats are not friendly for this. BigDecimals are. This should give you a start, needs error checking of course.

static String roundToLastTwoDecimalDigits(float f) {
    // split whole number and decimals
    String[] floatParts = new BigDecimal(f).toPlainString().split("\\.");

    int wholeNumberPortion = Integer.parseInt(floatParts[0]);

    // count zeroes
    String decimalPortion = floatParts[1];
    int numDecimalPlaces = 0;
    while (decimalPortion.charAt(numDecimalPlaces) == '0')
        numDecimalPlaces++;

    // get 3 digits to round
    String toRound = decimalPortion.substring(numDecimalPlaces,
            numDecimalPlaces + 3);

    int decimalForRounding = Math.round(Float.parseFloat(toRound) / 10);

    StringBuilder sb = new StringBuilder();

    sb.append(wholeNumberPortion);
    sb.append(".");
    for (int i = 0; i < numDecimalPlaces; i++)
        sb.append("0");
    sb.append(decimalForRounding);

    return sb.toString();
}
like image 58
Compass Avatar answered Mar 04 '26 10:03

Compass



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!