TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
 Specialized Dev Zones Research Center eBook Library .NET Java C++ Web Dev Architecture Database Security Open Source Enterprise Mobile Special Reports 10-Minute Solutions DevXtra Blogs Slideshow

# Formatting Floating Point Numbers-3 : Page 3

 by Danny Kalev
 Jun 7, 2006
 Page 3 of 3

### WEBINAR:On-Demand

Building the Right Environment to Support AI, Machine Learning and Deep Learning

Going Dotty
The formatting operation consists of locating the decimal point's position. If the number of fractional digits is higher than decplaces, do_fraction() will remove the remaining digits.

To locate the decimal point, use string::find(). Remember that STL algorithms use an agreed-upon constant to report a "value not found" condition. In the case of string, this constant is called string::npos:

``````
char DECIMAL_POINT='.'; // use ',' in European locales

size_t n=str.find(DECIMAL_POINT);
if ((n!=string::npos)// is there a decimal point?
{
//check the number of fractional digits
}
``````
If there's no decimal point, do_format() returns the string as is. Otherwise, do_format() checks whether the number of fractional digits is higher than decplaces. If it is, the fractional part is truncated:
```

.qs-listings #asset-middle-b .group {
width: 70% !important;;
}

.qs-listings #bottomline {
width: 70% !important;
}

```
size_t n=str.find(DECIMAL_POINT);
if ((n!=string::npos)// is there a decimal point?
&&(str.size()> n+decplaces))//is it followed by at
//least decplaces digits?
//write nul instead of the first digit after decplaces
str[n+decplaces]='\0';
``````
The last line of code overwrites the first superfluous fractional digit. It uses the \0 constant to chop the string at the right place. Notice, however, that string objects' data may contain nul characters; the actual length of the string is determined by the value returned from size(). Therefore, you can't assume that, at this stage, the string is formatted correctly. In other words, if str contained "123.4567" originally, after the insertion of the \0 constant it contains "123.45\07". To shrink str to "123.45", use the self-swapping idiom:
``````
str.swap(string(str.c_str()) );//get rid of spurious
//characters after the nul
``````
How does it work? The string::c_str() function returns a const char * representation of the string object. This value is used as the initializer of a temporary string object. Then, the temporary is used as the argument for str.swap(). This swap() call assigns the value "123.45" to str. Some older compilers that don't support default template arguments might not accept this swap call. In this case, use manual swapping instead:
``````
string temp=str.c_str();
str=temp;
``````
This isn't the most elegant code but it gets the job done.

No Strings Attached
Here's the complete code for do_fraction():

``````
string do_fraction(long double value, int decplaces=3)
{
ostringstream out;
int prec=
numeric_limits<long double>::digits10; // 18

out.precision(prec);//override default
out<<value;
string str= out.str(); //extract string from stream
size_t n=str.find(DECIMAL_POINT);
if ((n!=string::npos) //is there a decimal point?
&& (str.size()> n+decplaces)) //is it followed by at
//least decplaces digits?
{
str[n+decplaces]='\0';//overwrite first redundant digit
}

str.swap(string(str.c_str()));//get rid of spurious
//characters after the nul
return str;
}
``````
If you're wary about returning a string object by value, pass a string object by reference as an argument:
``````
void do_fraction(long double value, string & str, int decplaces=3);
``````
Personally, I prefer to trust my compiler for applying this optimization automatically. In addition, using string as the return value enables you to use do_fraction() in the following manner:
``````
cout << funct(123456789.69999001) << '\t' <<
funct(12.011)<<endl;//

//output:
123456789.69    12.01
``````

Danny Kalev is a certified system analyst and software engineer specializing in C++. He was a member of the C++ standards committee between 1997 and 2000 and has since been involved informally in the C++0x standardization process. He is the author of "The ANSI/ISO Professional C++ Programmer's Handbook" and "The Informit C++ Reference Guide: Techniques, Insight, and Practical Advice on C++."