For certain reasons (e.g. precision issue), some programmer may store a float value (e.g. money) in integer variable. For example -12345678.90 is stored as -1234567890. To convert the integer value to number with number of decimal places is a problem.
There are several way to do it. You can simply use the Java’s String.format(), DecimalFormat or Float.toString(). Most of them does not meet my requirements: Simple, fast, precise and with thousand separator. Therefore I wrote a simple class that ease myself.
public class MyFormat {
public static String format(int value, int nodp) {
int mod;
StringBuilder str;
char[] stack;
int i;
boolean negative;
boolean firstZero;
int comma;
negative = false;
if (value<0) {
negative = true;
value = -value;
}
stack = new char[15];
i = stack.length;
str = new StringBuilder();
while (nodp > 0) {
mod = value % 10;
value = value / 10;
stack[--i] = (char) ('0' + mod);
nodp--;
}
stack[--i] = '.';
firstZero = true;
comma = 0;
while (firstZero || value > 0) {
mod = value % 10;
value = value / 10;
stack[--i] = (char) ('0' + mod);
firstZero = false;
comma ++;
if (comma == 3) {
comma = 0;
if (value > 0)
stack[--i] = ',';
}
}
if (negative) str.append('-');
while(i< stack.length) {
str.append(stack[i++]);
}
return str.toString();
}
}
I also wrote a test program to test it’s performance and precision. The test program runs 100,000 loops for each format method and print out the formatted value. Here is the test program:
public class Test {
public static void main(String[] args) {
long start;
long end;
int loop = 100000;
int value = -1234567890;
int i;
// Use String.format
Integer integral = value/100;
Integer frag = value>0?value%100:-value%100;
start = System.currentTimeMillis();
for (i = 0; i < loop; i++)
String.format("%d.%02d", integral, frag);
end = System.currentTimeMillis();
System.err.println("1. String format: " + (end-start) + "ms");
System.err.println("1. String format: " + String.format("%d.%02d", integral, frag));
// Use DecimalFormat
DecimalFormat df;
float fvalue = value/100.0f;
df = new DecimalFormat("0.00");
df.setGroupingUsed(true);
df.setGroupingSize(3);
start = System.currentTimeMillis();
for (i = 0; i < loop; i++)
df.format(fvalue);
end = System.currentTimeMillis();
System.err.println("2. DecimalFormat format: " + (end-start) + "ms");
System.err.println("2. DecimalFormat format: " + df.format(fvalue));
// User Float.toString
start = System.currentTimeMillis();
for (i = 0; i < loop; i++)
Float.toString(fvalue);
end = System.currentTimeMillis();
System.err.println("3. Float.toString format: " + (end-start) + "ms");
System.err.println("3. Float.toString format: " + Float.toString(fvalue));
// Use my own format
start = System.currentTimeMillis();
for (i = 0; i < loop; i++)
MyFormat.format(value, 2);
end = System.currentTimeMillis();
System.err.println("4. My format: " + (end-start) + "ms");
System.err.println("4. My format: " + format(value, 2));
}
}
And this is the result:
1. String.toString format: 634ms 1. String.toString format: -12345678.90 2. DecimalFormat format: 322ms 2. DecimalFormat format: -12,345,679.00 3. Float.toString format: 54ms 3. Float.toString format: -1.2345679E7 4. My format: 60ms 4. My format: -12,345,678.90
The results shows that my program is 10 times faster than String.format, 5 times faster than DecimalFormat and as fast as Float.toString.
The String.format way shows the result I wanted but it is too slow and unexceptable.
The DecimalFormat way shows the inprecise value (-12,345,679.00) and it is slow too.
The Float.toString way shows the inprecise value and it is not the format I wanted.
impressed!!!