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)
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With