简体   繁体   中英

C++ how to avoid trailing zeroes?

If you do

double number;
cout.precision(3)
cout<<number;

for a number like 1.23456 you get 1.234 but if the number is 1.2 you get 1.200. How to get both 1.234 and 1.2 (they are useless zeroes)? Suppose you don't know what number you have to print.

#include <iostream>
#include <iomanip>
using namespace std;

auto main() -> int
{
    cout << setprecision( 4 );
    cout << 1.23456 << endl;        // -> "1.235"
    cout << 1.2 << endl;            // -> "1.2"
}

It's that simple: it's what you get by default.


C++03 lacked a manipulator for resetting to default formatting after setting fixed or scientific . However, in C++11 the defaultfloat manipulator was introduced. You can use it like this:

#include <iostream>     // defaultfloat
#include <iomanip>      // setprecision
using namespace std;

#ifdef __GNUC__ // Also check for version number, e.g. 4.8.2 and earlier
    namespace std {
        inline
        auto defaultfloat( ios_base& stream )
            -> ios_base&
        { stream.unsetf( ios_base::floatfield ); return stream; }
    }
#endif

auto main() -> int
{
    cout << "Lots of digits: " << fixed << setprecision( 16 ) << 1.2 << endl;
    cout << endl;

    cout << "Deault presentation:" << endl;
    cout << defaultfloat;
    cout << 1.234 << endl;
    cout << 1.2 << endl;
}

You might write a manipulator to achieve your formatting:

#include <cmath>
#include <iostream>

template <typename T>
struct DecimalPrecision
{
    const T& value;
    const unsigned decimals;

    DecimalPrecision(const T& value, unsigned decimals)
    : value(value), decimals(decimals)
    {}

    void write(std::ostream& stream) const {
        std::ios_base::fmtflags flags = stream.flags();
        stream.unsetf(std::ios_base::floatfield);
        std::streamsize restore
            = stream.precision(std::ceil(std::log10(std::abs(value))) + decimals);
        stream << value;
        stream.precision(restore);
        stream.flags(flags);
    }
};

template <typename T>
inline DecimalPrecision<T> decimal_precision(const T& value, unsigned decimals) {
    return DecimalPrecision<T>(value, decimals);
}

template <typename T>
inline std::ostream& operator << (std::ostream& stream, const DecimalPrecision<T>& value) {
    value.write(stream);
    return stream;
}


#include <iomanip>

int main()
{
    std::cout << std::setprecision(2);
    double values[] = { 12345.6789, 1.23456789, 1.2 };
    for(unsigned i = 0; i < sizeof(values)/sizeof(values[0]); ++i)
        std::cout
            << i << ": "  << values[i] << '\n'
                 << "   " << decimal_precision(values[i], 2) << '\n';
}

Did you even try your own example? Trailing zeroés are NOT printed (by default).

In fact, one usually wants (!) those zeroes (they convey information and they avoid clobbering up the output). This is achieved by cout << std::fixed.

Unless you have used std::fixed, 1.2 will produce 1.2, NOT 1.200, even with precision higher than 2.

BTW: Precision means all digits, not just those after the dot, hence precision=3 leads to 1.23 - UNLESS you go std::fixed, then only those after the dot are counted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM