Setting minimum number of decimal places for std::ostream precision
Asked Answered
K

2

18

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!

Kimberlykimberlyn answered 22/3, 2010 at 2:4 Comment(3)
Read the question carefully. Phil wants a MINIMUM of 1 digit of precision after the decimal point, but more if there is non-zero digits.Postiche
@Phil: You might find #2476142 helpful.Adulthood
Thanks Roger. That's very helpful. Your formatter example looks like the right way to go.Kimberlykimberlyn
P
2

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.

Postiche answered 22/3, 2010 at 2:21 Comment(11)
+1, though it's still unclear to me what he wants exactly, beyond zero being exactly "0.0".Adulthood
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...Kimberlykimberlyn
@Phil: What about 0.12, is output as "0.120000" okay? Why isn't "0.000000" fine? (Exactly what requirement does it fail?)Adulthood
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.Kimberlykimberlyn
@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.)Adulthood
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.Kimberlykimberlyn
@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."Adulthood
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' ;)Kimberlykimberlyn
@Roger, to be fair, I do hint at a solution (convert to string, strip trailing zeros) which I thought was trivial enough to implement.Postiche
@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.)Adulthood
@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.Postiche
I
4
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;
Intoxicated answered 22/3, 2010 at 2:11 Comment(5)
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?Kimberlykimberlyn
@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).Adulthood
You can do something like this. cout << setprecision(d?9:1) << fixed << d << endl;Intoxicated
Nice shortcut. Might be a bit cumbersome in implementation as I'd need to have a setprecision call in every output stream.Kimberlykimberlyn
@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.Adulthood
P
2

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.

Postiche answered 22/3, 2010 at 2:21 Comment(11)
+1, though it's still unclear to me what he wants exactly, beyond zero being exactly "0.0".Adulthood
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...Kimberlykimberlyn
@Phil: What about 0.12, is output as "0.120000" okay? Why isn't "0.000000" fine? (Exactly what requirement does it fail?)Adulthood
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.Kimberlykimberlyn
@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.)Adulthood
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.Kimberlykimberlyn
@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."Adulthood
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' ;)Kimberlykimberlyn
@Roger, to be fair, I do hint at a solution (convert to string, strip trailing zeros) which I thought was trivial enough to implement.Postiche
@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.)Adulthood
@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.Postiche

© 2022 - 2024 — McMap. All rights reserved.