HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Printing doubles using string manipulation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
doublesprintingmanipulationusingstring

Problem

Having mostly used Qt and its classes like QString, I wrote a little exercise with plain C++11. I'm looking for two kinds of input: generally improving the code and/or doing it better in an entirely different way (still standard C++11 or C++14, no Boost or anything).

The code is for printing doubles with given number of significant digits, by first producing a string using scientific notation, and then manipulating that string to move the dot and pad it with zeros.

#include 
#include 
#include 
#include 
#include 
#include 

template 
std::string number_to_sci_string(T number, int precision) {
    std::stringstream ss;
    ss = s.length()-1 || // must not be last
        e_pos - dot_pos (part2.length());
        if (exponent >= part2length) {
            auto fill = std::string(exponent - part2length, '0');
            return part1 + part2 + fill;
        }
        else if (exponent  nums{ -2000.0005, -1.2345234, -0.000011345, 0, 0.0000001, 0.1342134, 1.1234, 10000 };
    for_each(nums.begin(), nums.end(), [](double &n) {
        string sci = number_to_sci_string(n, 5);
        string nor = sci_string_to_normal(sci);
        cout << n << ": " << sci << " == " << nor << endl;
    });
}

Solution

-
number_to_sci_string looks ok, though you could considerably improve performance by chucking the template, restricting to float, double and long double and using snprintf:

std::string number_to_sci_string(long double number, int precision) {
    std::string s(std::snprintf(0, 0, "%.*Le", precision-1, number), '\0');
    std::snprintf(&s[0], s.size()+1, "%.*Le", precision-1, number);
    return s;
}


Also, I really wonder why you are using a different notion of precision than the standard library...

-
I suggest you be a bit more flexible in what you accept:

  • The exponent e00 should be optional.



  • The fractional part (and decimal point) .00 should be optional.



  • If there's a fractional part, the integer part should be optional.



-
Don't use using namespace std;, even in the implementation-file: You don't control what symbols it contains, and there are no guarantees none are added.

-
The opening brace of main()'s body is, in contrast to all other functions, on a separate line. Why?

-
Prefer the for-range-loop to std::for_each+lambda. The compiler should compile both to the same result, but the former is simpler and looks better.

Code Snippets

std::string number_to_sci_string(long double number, int precision) {
    std::string s(std::snprintf(0, 0, "%.*Le", precision-1, number), '\0');
    std::snprintf(&s[0], s.size()+1, "%.*Le", precision-1, number);
    return s;
}

Context

StackExchange Code Review Q#110496, answer score: 3

Revisions (0)

No revisions yet.