Search code examples
c++printf

how to let ss << f work like printf("%g", f);


In my C++ program, the initial code is

stringstream ss;
vector<float>::iterator v;
ss << std::left << std::setw(12) << std::setiosflags(std::ios::fixed)
                << std::setprecision(6) << *v;

But for some v, for example, 2345999998888.44445332222, the output will be very long. So I want that

ss << *v

has the same effect like

printf("%g", f);

and later, I just used ss << *v. Amazingly, the output is the same like %g does.

Does stringstream automatically choose the better way to output a value? Or I just made a tricky mistake?


Solution

  • %g is documented as follows:

    converts floating-point number to decimal or decimal exponent notation depending on the value and the precision.

    For the g conversion style conversion with style e or f will be performed.

    For the G conversion style conversion with style E or F will be performed.

    Let P equal the precision if nonzero, 6 if the precision is not specified, or 1 if the precision is ​0​. Then, if a conversion with style E would have an exponent of X:

    • if P > X ≥ −4, the conversion is with style f or F and precision P − 1 − X.

    • otherwise, the conversion is with style e or E and precision P − 1.

    Unless alternative representation is requested the trailing zeros are removed, also the decimal point character is removed if no fractional part is left. For infinity and not-a-number conversion style see notes.

    The stream equivalent would look something like this:

    #include <cmath>
    
    float f = ...;
    int X; // the exponent
    int P = 6; // the desired precision
    
    X = std::floor(std::log10(f));
    
    std::stringstream ss;
    if ((P > X) && (X >= −4))
        ss << std::fixed << std::setprecision(P - 1 − X);
    else
        ss << std::scientific << std::setprecision(P - 1); 
    ss << f;