A faster alternative to DecimalFormat.format()?
You can write your own routine given you know exactly what you want.
public static void appendTo6(StringBuilder builder, double d) {
if (d < 0) {
builder.append('-');
d = -d;
}
if (d * 1e6 + 0.5 > Long.MAX_VALUE) {
// TODO write a fall back.
throw new IllegalArgumentException("number too large");
}
long scaled = (long) (d * 1e6 + 0.5);
long factor = 1000000;
int scale = 7;
long scaled2 = scaled / 10;
while (factor <= scaled2) {
factor *= 10;
scale++;
}
while (scale > 0) {
if (scale == 6)
builder.append('.');
long c = scaled / factor % 10;
factor /= 10;
builder.append((char) ('0' + c));
scale--;
}
}
@Test
public void testCases() {
for (String s : "-0.000001,0.000009,-0.000010,0.100000,1.100000,10.100000".split(",")) {
double d = Double.parseDouble(s);
StringBuilder sb = new StringBuilder();
appendTo6(sb, d);
assertEquals(s, sb.toString());
}
}
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
long start = System.nanoTime();
final int runs = 20000000;
for (int i = 0; i < runs; i++) {
appendTo6(sb, i * 1e-6);
sb.setLength(0);
}
long time = System.nanoTime() - start;
System.out.printf("Took %,d ns per append double%n", time / runs);
}
prints
Took 128 ns per append double
If you want even more performance you can write to a direct ByteBuffer (assuming you want to write the data somewhere) so the data you produce does need to be copied or encoded. (Assuming that is ok)
NOTE: this is limited to positive/negative values of less than 9 trillion (Long.MAX_VALUE/1e6) You can add special handling if this might be an issue.
Maybe your program doesn't do much intensive work and so this appears to do the most - crunching some numbers.
My point is that your results are still relative to your app.
Put a timer around each DecimalFormatter.format() and see how many millis you are using to get a clearer picture.
An alternative would be to use the string Formatter, give it a try to see if it performs better:
String.format("%.6f", 1.23456789)
Or even better, create a single formatter and reuse it - as long as there are no multithreading issues, since formatters are not necessarily safe for multithreaded access:
Formatter formatter = new Formatter();
// presumably, the formatter would be called multiple times
System.out.println(formatter.format("%.6f", 1.23456789));
formatter.close();