Your algorithm looks fine. StringBuffer
is thread safe and therefore quite slow because it acquires a lock for each call to append
. Use StringBuilder
, and construct it with the capacity you know you'll need, i.e. k
. This prevents multiple copies of the data as the buffer inside StringBuilder
is expanded to accomodate the growing string.
This is clear if you read the StringBuffer
docs:
As of release JDK 5, this class has been supplemented with an equivalent class designed for use by a single thread, StringBuilder. The StringBuilder class should generally be used in preference to this one, as it supports all of the same operations but it is faster, as it performs no synchronization.
Since you know the exact size of the output in advance, you can also use an array of bytes to hold the digits. Still final conversion to a string of length 10^6 and output are expensive. When I run the code below, it takes only 0.016 seconds to create the byte array, 0.06 to convert to a string, and over 1 second to print. To make progress, you will have to do some research on how to do fast i/o in Java. If you swith to C or another language closer to the hardware, the normal i/o routines may be fast enough.
public void run() {
int k = 1000000;
long start = System.currentTimeMillis();
int tot = 4687;
int divisor = 33102;
byte [] buf = new byte[k];
int tmp = tot;
for (int i = 0; i < k; i++) {
tmp = tmp * 10;
int res = tmp / divisor;
buf[i] = (byte)(res + '0');
tmp = tmp - res * divisor;
}
System.out.println((System.currentTimeMillis() - start) * .001);
String s = new String(buf);
System.out.println((System.currentTimeMillis() - start) * .001);
System.out.print("3."); System.out.println(s);
System.out.println((System.currentTimeMillis() - start) * .001);
}