views:

341

answers:

2

Hi,

Is there a way to set the "minimum" number of decimal places that a std::ostream will output?

For example, say I have two unknown double variables that I want to print (values added here for the sake of illustration):

double a = 0;
double b = 0.123456789;

I can set my maximum decimal precision so that I output b exactly

std::cout << std::setprecision(9) << b << std::endl;
>>> 0.123456789

Is there a way to set a "minimum" precision (a minimum number of decimal places), while retaining the "maximum" precision, so that

std::cout << a << std::endl << b << std::endl;

yields

0.0
0.123456789

not

0
0.123456789

?

Thanks! Phil


the short answer to this is "No". The stream has only one precision setting, with no facility to differentiate between maximum and minimum precision. Thanks all for your generous advice!

A: 
cout << setprecision(1) << fixed << d << endl;

Used fixed after setprecision.

Edit: This is what you want. It would change precision based on d.

cout << setprecision(d?9:1) << fixed << d << endl;
Sameer
Thanks Sameer. However that assumes that I know beforehand that d=0. Is there a solution for an arbitrary d that would print "0.0" if d=0, but "0.123456789" if d=0.123456789?
Phil Boltt
@Phil: The stream only has one precision setting. You could check the value before you output it, and output your `"0.0"` then (note that is a string literal, not a double).
Roger Pate
You can do something like this.cout << setprecision(d?9:1) << fixed << d << endl;
Sameer
Nice shortcut. Might be a bit cumbersome in implementation as I'd need to have a setprecision call in every output stream.
Phil Boltt
@Phil: `if (d) cout << d; else cout << "0.0";` is better (and you'd keep the stream with the desired fixed/precision settings, you don't have to repeat those unless they changed since the last output). Also realize you might want something like `if (fabs(d) > some_tolerance)` because floating point math is inexact.
Roger Pate
+1  A: 

I do not think there is a way to achieve what you are asking without turning the number into a string (with high precision), and stripping off the trailing zeros.

This is appropriate, because just because there are trailing zeros doesn't mean there isn't precision there, and the run-time can't tell that.

For example, if I measure the weight of an object with a cheap scale, it may be 1.0 kgs.

If I weigh it with a high-accuracy scale, it may be 1.00000 kgs. Just because there are trailing zeros, doesn't mean that accuracy should be discarded.

Oddthinking
+1, though it's still unclear to me what he wants exactly, beyond zero being exactly "0.0".
Roger Pate
Nothing more than that, Roger. I have a requirement that floats or double are represented in the output stream with a decimal place and I'm just looking for a way to do this elegantly without implying the kind of accuracy precision that Oddthinking refers to above. Hence 0 should be represented as 0.0, not 0.0000...
Phil Boltt
@Phil: What about 0.12, is output as "0.120000" okay? Why isn't "0.000000" fine? (Exactly what requirement does it fail?)
Roger Pate
If I had the option of setting a minimum precision then I could just set a maximum precision (setprecision(9)) and have the best of both worlds. 0.12 output as "0.12" while 0.123456789 is output as "0.123456789". As to why 0.000000 isn't fine? Unfortunately that's a convoluted story involving legacy implementations and historic data.
Phil Boltt
@Phil: If you merely need 0.0 treated specially, then do only that, but make sure you know why using fabs (as I showed in another comment) is useful. If you need to strip *all* trailing zeros, the question I linked (in the comment on the question above) will work. (And maybe you could edit the question with the clearer requirements and someone can add/edit an answer to match them.)
Roger Pate
I'm not sure that my original question was terribly unclear. Perhaps my reason for asking it was, but the question itself is whether it is possible to set a minimum number of decimal places on a std::ostream. The answer, as you mentioned in one comment, is no, because the stream has only one precision setting.
Phil Boltt
@Phil: Ah, then I read too much into your question, thinking you wanted to solve the problem instead of just be told "no". :P It's that programmers' riddle: "Would you like to win the lottery or find true love?" .. "Yes."
Roger Pate
Fair enough ;) But thanks for pointing me to a solution regardless of my peculiar requirements. btw.. I would also have accepted 'yes - just blah blah blah' ;)
Phil Boltt
@Roger, to be fair, I do hint at a solution (convert to string, strip trailing zeros) which I thought was trivial enough to implement.
Oddthinking
@Oddthinking: Sorry I hijacked your answer to talk to Phil, but I'm not sure what you're replying to there. (I didn't find anything wrong with your answer, and am the one who upvoted it.)
Roger Pate
@Roger, nothing to apologise for - I'm happy for the discussion. I was reacting to the (unintended?) suggestion that this answer merely just told Phil "no", rather than giving him a useful direction to proceed.
Oddthinking