Fast Numerical Formatting
Environment: VC6 SP4, W2k SP2
Display of the most financial data is required to be formated with a thousand separator. Like: 1000000 to be formated and displayed as "1,000,000"
There are lots of ways to do this formating, but there is no default crt function to do this for you. Here I try to present 2 functions, with very good performance that can be used for this this type of formating. Here is the most simple implementation.
static char sDecimalSeparator = '.'; // dot by default static char sThousantSeparator =','; // comma by default // call this to format a long to a string static char* __stdcall long2str( char* szBuffer, long lValue ) { char *p; // pointer to traverse string char *firstdig; // pointer to first digit char temp; // temp char unsigned digval; // value of digit unsigned long val; p = szBuffer; if (lValue < 0 ) { // negative, so output '-' and negate *p++ = '-'; val = (unsigned long)(-(long)lValue); // make it positive!! } else val = lValue; firstdig = p; // save pointer to first digit int iDecimalPos = 0; do { iDecimalPos ++; if (iDecimalPos != 4) { digval = (unsigned) (val % 10); val /= 10; // get next digit *p++ = (char) (digval + '0'); // and store the digit } else { *p++ = sThousantSeparator; iDecimalPos = 0; } } while (val > 0); // We now have the digit of the number in the buffer, // but in reverse order. Thus we reverse them now. *p-- = '\0'; // terminate string; p points to last digit do { temp = *p; *p = *firstdig; *firstdig = temp; // swap *p and *firstdig --p; ++firstdig; } while (firstdig < p); // repeat until halfway return szBuffer; }
Now, most of the financial data is displayed with a sign as a number trailer.
eg: 1000+ or 1000-
Here is a new implementation one with this new functionality: adding the sign after the number, regarding it's positive or negative.
static char sDecimalSeparator = '.'; // dot by default static char sThousantSeparator =','; // comma by default // call this to format a long to a string // iShowSign = 0 - show only the default "-" sign // iShowSign = 1 - show minus/plus signs always at the // begining of the number (eg: +1000, -1000) // iShowSign = 2 - show minus/plus signs always at the // end of the number (eg: 1000+, 1000-) static char* __stdcall long2str( char* szBuffer, long lValue, int iShowSign = 0 ) { char *p; // pointer to traverse string char *firstdig; // pointer to first digit char temp; // temp char unsigned digval; // value of digit unsigned long val; p = szBuffer; if (lValue < 0 ) { // negative, so output '-' and negate if (iShowSign < 2) *p++ = '-'; val = (unsigned long)(-(long)lValue); // make it positive!! } else { if ( iShowSign == 1 ) *p++ = '+'; val = lValue; } firstdig = p; // save pointer to first digit int iDecimalPos = 0; do { iDecimalPos ++; if (iDecimalPos != 4) { digval = (unsigned) (val % 10); val /= 10; // get next digit *p++ = (char) (digval + '0'); // and store the digit } else { *p++ = sThousantSeparator; iDecimalPos = 0; } } while (val > 0); // We now have the digit of the number in the buffer, // but in reverse order. Thus we reverse them now. // Check if we have to add signs if ( iShowSign == 2 ) { if ( lValue < 0 ) *p++ = '-'; else *p++ = '+'; *p-- = '\0'; // terminate string; p points to last digit *p--; // go back one more step to leave the sign sign intact! } else { *p-- = '\0'; // terminate string; p points to last digit } do { temp = *p; *p = *firstdig; *firstdig = temp; // swap *p and *firstdig --p; ++firstdig; } while (firstdig < p); // repeat until halfway return szBuffer; }
I hope that this is as useful to you, as it would have been for me some time ago. If you have implementations that are faster than those two, please send them to me.
More for Developers
Top Authors
- Voted: 13 times.
- Voted: 11 times.
- Voted: 11 times.
- Voted: 10 times.
- Voted: 8 times.
- Paul Kimmel 214 articles
- Zafir Anjum 120 articles
- Tom Archer - MSFT 83 articles
- Mark Strawmyer 78 articles
- Jeffrey Juday 74 articles