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– = ‘’; // 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– = ‘’; // terminate string; p points to last digit
*p–; // go back one more step to leave the sign sign intact!
} else
{
*p– = ‘’; // 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 by Author

Must Read