Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::setprecision(6) stream more than six digits in fixed-width mode?

The output of the following code:

#include <limits>
#include <iostream>
#include <iomanip>
#include <limits>
#include <string>
#include <sstream>

using namespace std;

inline string lexical_cast(const float arg)
{
    stringstream ss;
    ss << fixed << setprecision(numeric_limits<float>::digits10) << arg;
    if (!ss)
        throw "Conversion failed";

    return ss.str();
}

int main()
{
    cout << numeric_limits<float>::digits10 << '\n';
    cout << lexical_cast(32.123456789) << '\n';
}

is:

6
32.123455

I expected, and wanted:

6
32.1234

because, to the best of my knowledge, that's the extent of what a float can reliably give me on my system.

How can I persuade IOStreams to behave as I want?

like image 372
Lightness Races in Orbit Avatar asked Dec 15 '22 00:12

Lightness Races in Orbit


1 Answers

In fixed-width mode the "precision" setting is used as the number of decimal places, in contrast with scientific mode where it is used as the number of significant digits. IOStreams provides no mechanism to use "precision" as the number of significant digits without using scientific mode.

There is a third mode, which in C++11 is activated with std::defaultfloat. This "default" mode is what you get if you don't set either fixed or scientific mode. You can re-activate it in C++03 by resetting the float flags with s.unsetf(std::ios_base::floatfield). This mode is a bit of a mix between scientific and some sort of "fixed without trailing zeros".

like image 114
R. Martinho Fernandes Avatar answered Apr 26 '23 23:04

R. Martinho Fernandes