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.
siewting says
impressed!!!