Double in C + + converted to string (formatted for floating-point numbers)

Source: Internet
Author: User
Tags truncated

In everyday programming-including dialog boxes, relational database, financial procedures, SMS programs and all procedures for processing data files, the need to control the decimal point after the situation is very common, this article will explain how to use a simple method to control the decimal places, in addition, to uncover the string and data precision a little secret.

the problem arises

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 face of it, this is a small programming problem, but if you really want to use it in practice, the function should be designed to be flexible to allow callers to specify the number of decimal places. In addition, functions should be able to handle a variety of exception situations, such as integers like 123.0 or 123.

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

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

Mantra 2: Use a library when you want to convert to a string.

The interface of the transformation function is very concise: the first parameter is the numeric value that needs to be formatted, and the second parameter represents the decimal places 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 a decimal point, so the two-bit decimal requires a default value of 3.

Precision Problems

Of course, the first step is to convert a long double to a string, and using the standard C + + library is simply extremely easy. However, one thing must be noticed, for some reason, the default precision of the StringStream object is 6, and many programmers mistakenly interpret "precision" as a decimal digit, which is incorrect, and the precision should refer to the total number of digits. Thus, the number 1234.56 can safely be represented by the default precision 6来, but 12345.67 will be truncated to 12345.6. In this case, if you have a very large number, such as 1234567.8, its result will be quietly converted to the scientific notation: 1.23457e+06, which is obviously not what we want. To avoid such trouble, you should set the default precision to the maximum before you begin 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; Recision (PREC);//overwrite default precision out << value; String str = OUT.STR (); Fetching string values from the stream is now stored in STR and waits for formatting.

position of decimal point

To format, you first need to determine the position of the decimal point, if the number of decimal places is more than decplaces,do_fraction () will remove the redundant.

To locate decimal places, you can use String::find () to use a constant in the STL algorithm to represent "value not found", in the string, this constant is String::npos:

Char decimal_point= '. '; European usage for ', ' size_t n=str.find (decimal_point); if (N!=string::npos)//whether there is a decimal point. {//check number of decimal digits}

If there is no decimal point, the function returns the string directly, otherwise the function will continue to check whether the decimal bit is more than decplaces. If so, the decimal part will be truncated:

size_t N=str.find (Decimal_point); if (N!=string::npos)//has a decimal point. && (Str.size () > N+decplaces))//There are at least decplaces digits behind. Write nul str[n+decplaces]= ' decplaces ' after decimal digits;

The last line overrides the extra decimal bit, which uses the override constant to truncate the string, noting that the string object's data can contain NUL characters, and that the actual length of the string is determined by the return value of size (). Therefore, you cannot assume that the string has been properly formatted, in other words, if it is "123.4567" in the STR Central, and after inserting the constant, it becomes "123.45\07", and in order to reduce STR to "123.45", a method of self swapping is generally available:

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

So what is the principle of it? 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 an argument to Str.swap (), and Swap () will "123.45" Assigned to Str. Some older compilers do not support default template parameters, and may not allow swap () to be compiled, and if so, use manual swapping instead:

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

Although the code is not very "graceful", but can achieve the purpose on the line. 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)//has a decimal point.  && (Str.size () > N+decplaces))//There are at least decplaces digits behind. {str[n+decplaces]= ';//overwrite the first extra number} Str.swap (String (Str.c_str ()));//Remove extra characters after nul to 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 standpoint, the compiler is inclined to make such an optimization, in addition, by using the return of value, you can 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.