Combining fixed and scientific in stringstream

J

Johannes Bauer

Hello group,

I've a simple problem with the precision specifiers of stringstream.
Let's say I have this:

double x = 123.4567890;
std::stringstream Strm;
Strm.precision(4);
Strm << std::scientific << x;
std::cerr << Strm.str() << std::endl;

It will display "123.4". Now when I change x to be 1, it will display
"1". However, in that case I'd prefer if it could display "1.000", i.e.
not making the precision field the *minimum* precision but always the
exact displayed precision.

When I change to "fixed" I get the desired behavior - somehow, at least:
it only affects the digits after the decimal point, which is also what I
do not want. To sum it all up, here is what value yield which
representation and which I'd like:

Value scient fixed Preferred
1 1 1.0000 1.000
12 12 12.0000 12.00
123 123 123.0000 123.0
1.23 1.23 1.2300 1.230
1.234 1.234 1.2340 1.234
12345 1.234E4 12345.0000 1.234E4
10000 1E4 10000.0000 1.000E4

I don't know if this is possible, but I'm happy to hear any suggestions.

Thanks in advance,
Johannes
 
J

Johannes Bauer

Johannes said:
To sum it all up, here is what value yield which
representation and which I'd like:

Oh boy, that got messed up. Again, now with spaces instead of tabs
Value scient fixed Preferred
1 1 1.0000 1.000
12 12 12.0000 12.00
123 123 123.0000 123.0
1.23 1.23 1.2300 1.230
1.234 1.234 1.2340 1.234
12345 1.234E4 12345.0000 1.234E4
10000 1E4 10000.0000 1.000E4

Regards,
Johannes
 
M

Mirco Wahab

Johannes said:
Oh boy, that got messed up. Again, now with spaces instead of tabs

I don't know of any trick to format the
exponent in %g-mode, so this is what I have:

...
stringstream s;

s.setf(ios::fixed, ios::floatfield);
s << setw(5) << setprecision(3) << 1. << endl;
s << setw(5) << setprecision(2) << 12. << endl;
s << setw(5) << setprecision(1) << 123. << endl;
s << setw(5) << setprecision(3) << 1.23 << endl;
s << setw(5) << setprecision(3) << 1.234 << endl;

s.setf(ios::scientific, ios::floatfield);
s << setw(5) << setprecision(3) << 12345. << endl;
s << setw(5) << setprecision(3) << 10000. << endl;
...

An yes, Posix printf/sprintf is really powerful.
What's missing in std is a printf-conformal:
ostream& format(ostream&, "printf-format", value list)
or something like that.

Regards

M.
 
J

Johannes Bauer

Mirco said:
I don't know of any trick to format the
exponent in %g-mode, so this is what I have:
[...]

s << setw(5) << setprecision(3) << 1. << endl;
s << setw(5) << setprecision(2) << 12. << endl;
s << setw(5) << setprecision(1) << 123. << endl;

Well, yes, the output looks right - but the "setprecision" part will be
a pain to implement, probably... I just thought maybe C++ provided some
powerful means of formatting those values.
An yes, Posix printf/sprintf is really powerful.
What's missing in std is a printf-conformal:
ostream& format(ostream&, "printf-format", value list)
or something like that.

Yes, it is very much indeed :-(

printf is probably the thing I miss most when using C++. There it would
be a mere "%.3lf" and the thing would be done. Thing is, it's not
typesafe. If there were some way to gernerally format strings, that'd be
quite nice. I don't want to rely on sprintf with a C++ project though, I
have my doubts... I'll see what I come up with.

Thanks for your help,
Johannes
 
J

James Kanze

Mirco Wahab schrieb:

In general, you can't format the exponent, neither in %g nor in
%e (and nor with ostream nor with printf).
[...]
s << setw(5) << setprecision(3) << 1. << endl;
s << setw(5) << setprecision(2) << 12. << endl;
s << setw(5) << setprecision(1) << 123. << endl;
Well, yes, the output looks right - but the "setprecision"
part will be a pain to implement, probably... I just thought
maybe C++ provided some powerful means of formatting those
values.

The problem, really is that you want the formatting to depend
(at least partially) on the value. Neither C (printf) nor C++
really support this.

You might try setting showpoint, however. According to the
standard, this should be the equivalent of using the '#' flag in
printf, which forces trailing zeros in %g. So despite its name,
it should work for that, and does with g++. But you'll still
not get E4 when the %e format is used: the standards (both C and
C++) require E+04 (i.e. the sign, even if positive, and exactly
two digits, if it fits).

Funny, I never noticed that. The iostream formatters are a lot
more powerful, at least in terms of what you can do. And if
they don't suffice, of course, you just write a wrapper class,
Yes, it is very much indeed :-(
printf is probably the thing I miss most when using C++. There
it would be a mere "%.3lf"

That won't get the format you were requesting. What you were
requesting was basically '%#.4g" (but with a different format
for the exponent, if scientific format was used---which isn't
supported).

More generally, of course, you don't really want to specify such
details at the point of the output statement. You want to
specify what the value means, semantically, and then somewhere
globally (e.g. like in a style sheet) specify how such semantic
values are formatted. You can sort of do this with printf:

printf( ("some text " + semanticFormat + " so on).c_str(), ... ) ;

but it hardly seems natural. Where as iostream was designed
precisely with this in mind:

std::cout << "some text " << semanticFormat << value << " so
on" ...

The whole point of manipulators is that you write your own, for
your programs semantics, so that you don't have to specify the
physical details of formatting many times over, every time you
output a value representing the given semantics.
and the thing would be done. Thing
is, it's not typesafe.

And can't be generalized (i.e. to output to a socket, or with a
back end filter that inserts time stamps, or expands tabs). And
you more or less have to embed the physical formatting
information in with the normal text, which is totally wrong from
a software engineering point of view.
If there were some way to gernerally format strings, that'd be
quite nice. I don't want to rely on sprintf with a C++ project
though, I have my doubts... I'll see what I come up with.

You might want to have a look at Boost format. I've not had the
occasion to try it out myself, but from discussions with the
author, I think that it allows the use of manipulators for
format specifiers, but still allows keeping the text in a single
block (important for translation purposes).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top