Double in C + + converts to string type (formatting of floating-point numbers)

Source: Internet
Author: User
Tags truncated

In daily programming--including dialogs, relational databases, financial procedures, SMS programs, and all procedures for handling data files--it is common to control decimal places after decimals, and this article will explain how to use simple methods to control decimal places, and also to uncover a little bit of secrecy about string and data precision.

The derivation of the problem

If you have a function that accepts a long double argument and converts the argument to a string, the resulting string should retain two decimal places, for example, a floating-point value of 123.45678 should generate a string such as "123.45". On the surface, this is a programming problem with little meaning, but if it really comes in handy, the function should be designed to be resilient to allow callers to specify the number of decimal digits. In addition, the function should be able to handle a variety of exception conditions, such as integers like 123.0 or 123.

Before you begin, take a look at the two words "mantra" when writing "elegant" C + + code:

"Mantra" 1: Whenever you need to format a numeric value, you should first convert to a string. This guarantees that each digit occupies exactly one character.

"Mantra" 2: Use the library when you need to convert to a string.

The interface of the conversion function is very concise: the first parameter is the value to be formatted, the second parameter represents the decimal place that is displayed after the point, and should have a default value; The return value is a string type:

String do_fraction (long double value, int decplaces=3);

Note that the second parameter represents the decimal places that are included in the decimals, so a two-bit decimal number requires a default value of 3.

Accuracy issues

Of course, the first step is to convert a long double value into a string, which is simply extremely easy using the standard C + + library. However, one thing must be noticed, for some reason, the default precision of the StringStream object is 6, and many programmers mistakenly interpret the "precision" as the number of decimal places, which is incorrect, and the precision should refer to the total number of digits. Thus, the number 1234.56 is safely represented by the default precision 6来, but 12345.67 is truncated to 12345.6. In this case, if you have a very large number, such as 1234567.8, its results will be quietly converted to scientific notation: 1.23457e+06, which is obviously not what we want. To avoid such trouble, you should set the default precision to maximum before starting the conversion.
To get the maximum number of digits that a long double can represent, you can use the library:

String do_fraction (long double value, int decplaces=3) {int prec=numeric_limits::d igits10;//Ostringstream out; OUT.P Recision (PREC);//override default precision out << value; String str = OUT.STR (); The string values taken out of the stream are now stored in STR, waiting to be formatted.

The position of the decimal point

To format, first determine the position of the decimal point, if the number of decimal places more than Decplaces,do_fraction () will delete the superfluous.

To locate the decimal place, use String::find (), which uses a constant in the STL algorithm to represent "value not found", in the string, the constant is String::npos:

Char decimal_point= '. '; European usage for ', ' size_t n=str.find (decimal_point); if ((N!=string::npos)//Is there a decimal point? {//Check the number of decimal places}

If there is no decimal point, the function returns the string directly, otherwise the function will continue to check if the decimal place is more than decplaces. If so, the number of decimal points will be truncated:

size_t N=str.find (Decimal_point); if ((N!=string::npos)//Have a decimal point? && (Str.size () > N+decplaces))//Is there at least decplaces bit behind? Write nul str[n+decplaces]= ' + ' after the decimal decplaces bit;

The last line overrides the extra decimal bit, which uses the \ n constant to truncate the string, noting that the data of the string object can contain NUL characters, whereas the actual length of the strings is determined by the return value of size (). Therefore, you can not assume that the string has been properly formatted, in other words, if the str is "123.4567", after inserting the constant, it becomes "123.45\07", in order to reduce STR to "123.45", generally can use the self-exchange method:

Str.swap (String (Str.c_str ()));//delete extra characters after nul

So what is the principle of it? The function string::c_str () returns a const char * representing this string object, which is used as the initialization value for a temporary string object, and then the temporary object is used as the Str.swap () parameter, and swap () will value "123.45" Assigned to Str. Some older compilers do not support default template parameters and may not let swap () compile, and if so, use manual swapping instead:

String Temp=str.c_str (); Str=temp;

The code is not very "graceful", but it can be done with the goal. The following is the complete code for Do_fraction ():

 

string do_fraction (long double value, int decplaces=3)  {Ostringstream out; int prec= numeric_limits::d igits10;  Out.precision (PREC);//override default precision out<<value; String str= out.str ();  Remove the string from the stream size_t n=str.find (decimal_point); if ((N!=string::npos)//Have a decimal point? && (Str.size () > N+decplaces))//Is there at least decplaces bit behind? {str[n+decplaces]= ';//overwrite the first extra number} Str.swap (String (Str.c_str ()));//delete extra characters after nul return str; }

If you do not want to return a string object by passing a value, you can also add a parameter to pass the STR object as a reference:

void Do_fraction (long Double value, string & str, int decplaces=3);

From a personal point of view, it is still preferred to have the compiler do such optimizations, in addition, using the return value, you can also let you use Do_fraction () in the following way:

cout << funct (123456789.69999001) << ' \ t ' << funct (12.011) <<endl;

Output: 123456789.69 12.01

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.