Fixed Width Double String Conversion

I would like to print a double value in a string with a length of not more than 8 characters. The printed number must have as many digits as possible, for example

 5.259675 48920568 8.514e-6 -9.4e-12 

I tried C ++ iostreams and printf style, and not one of them respects the size provided as I would like:

 cout << setw(8) << 1.0 / 17777.0 << endl; printf( "%8g\n", 1.0 / 17777.0 ); 

gives:

 5.62525e-005 5.62525e-005 

I know I can indicate accuracy, but here I would have to provide very little accuracy to cover the worst case. Any ideas on how to ensure accurate field width without sacrificing too much accuracy? I need this to print matrices. Do I really need to come up with my own conversion function?

A similar question was asked 5 years ago: Convert double to String with a fixed width , without a satisfactory answer. I am sure that at the same time there has been some progress.

+6
source share
2 answers

This does not seem too complicated, in fact, although you cannot do it in a single function call. The number of character positions used by the exhibitor is really easy to predict:

 const char* format; if (value > 0) { if (value < 10e-100) format = "%.1e"; else if (value < 10e-10) format = "%.2e"; else if (value < 1e-5) format = "%.3e"; } 

etc.

Only, the C standard, which defines the behavior of printf, insists on at least two digits for the metric, so it discards some of them. See C ++ on how to get a “one exponent” with printf

Enabling these fixes will make the code quite complicated, although still not as bad as doing the conversion yourself.

+1
source

If you want to convert to fixed decimal numbers (for example, release the +/- "E" part), then this will greatly facilitate the execution:

 #include <stdio.h> #include <cstring> // strcpy #include <iostream> // std::cout, std::fixed #include <iomanip> // std::setprecision #include <new> char *ToDecimal(double val, int maxChars) { std::ostringstream buffer; buffer << std::fixed << std::setprecision(maxChars-2) << val; std::string result = buffer.str(); size_t i = result.find_last_not_of('\0'); if (i > maxChars) i = maxChars; if (result[i] != '.') ++i; result.erase(i); char *doubleStr = new char[result.length() + 1]; strcpy(doubleStr, (const char*)result.c_str()); return doubleStr; } int main() { std::cout << ToDecimal(1.26743237e+015, 8) << std::endl; std::cout << ToDecimal(-1.0, 8) << std::endl; std::cout << ToDecimal(3.40282347e+38, 8) << std::endl; std::cout << ToDecimal(1.17549435e-38, 8) << std::endl; std::cout << ToDecimal(-1E4, 8) << std::endl; std::cout << ToDecimal(12.78e-2, 8) << std::endl; } 

Output:

 12674323 -1 34028234 0.000000 -10000 0.127800 
0
source

Source: https://habr.com/ru/post/970124/


All Articles