This question has been asked a couple of times, but all the answers either refer to sprintf or involve deleting the trailing zeroes manually. Is there really no better way? is it not possible to achieve this with std::stringstream
?
Asked
Active
Viewed 1,427 times
1

Violet Giraffe
- 32,368
- 48
- 194
- 335
-
Have you tried using [`std::stringstream`](http://en.cppreference.com/w/cpp/io/basic_stringstream) or looked at any stream [releated documentation](http://en.cppreference.com/w/cpp/io/manip) yet? Have you tried narrowing down your search by including stringstream as part of your query? – Captain Obvlious Mar 04 '14 at 16:40
-
@CaptainObvlious: of course I did. – Violet Giraffe Mar 04 '14 at 17:28
-
Do you want to limit the fractional digits to no more than some number, N (with some form of rounding), or do you want all significant decimal fractional digits? – amdn Mar 04 '14 at 18:46
-
@Claptrap: I have defined it, read the question carefully. No `sprintf` and no manually deleting trailing zeroes. I. e., I'm looking for an STL solution, 1-2 lines of code. – Violet Giraffe Mar 04 '14 at 20:24
-
what is better with that? it will anyway be optimized. – AndersK Mar 04 '14 at 21:43
2 Answers
4
First you calculate how many potential digits you have before and after the decimal:
int digits_before = 1 + (int)floor(log10(fabs(value)));
int digits_after = std::numeric_limits<double>::digits10 - digits_before;
Then you find out how many of those digits are zeros:
double whole = floor(pow(10, digits_after) * fabs(value) + 0.5);
while (digits_after > 0 && (whole/10.0 - floor(whole/10.0)) < 0.05)
{
--digits_after;
whole = floor(whole / 10.0 + 0.5);
}
if (digits_after < 0) digits_after = 0;
Now you have a value you can use with std::setprecision
:
std::stringstream ss;
ss << std::fixed << std::setprecision(digits_after) << value;
Ultimately this is a lot of work and duplicates effort that the string conversion does anyway, which is why people generally just convert to a string and remove the trailing zeros. And no, there's no simple formatting option to do this, you have to do it the hard way or not at all.
See the above code in action: http://ideone.com/HAk55Y

Mark Ransom
- 299,747
- 42
- 398
- 622
-
This function (in ideone) doesn't seem to work with very small numbers like 0.00001, which will not be rendered in fixed point notation as was required. – eerorika Mar 04 '14 at 18:04
-
@user2079303, thanks for the heads up. It's easily fixed, see http://stackoverflow.com/questions/2335657/prevent-scientific-notation-in-ostream-when-using-with-double and http://ideone.com/N9PfIC. I'll update the answer. – Mark Ransom Mar 04 '14 at 19:23
-1
If the goal is to have a fixed point of x
or less for trailing zeros, toss the double through a fixed sstream. Then cut off the remaining with non fixed output.
double number = 1.03000;
std::stringstream s.precision(6);
s << number;
std::cout << s.str();
Edit: To save results
std::string result = s.str();

Lampshady
- 102
- 4
-
Except I need to get a string, not output the result to `cout`. – Violet Giraffe Mar 04 '14 at 17:31
-
@VioletGiraffe Then use something like `std::string st(s.str())` or `const std::string& st(s.str())`or pass the result of calling `s.str()` to whatever function you want. – Captain Obvlious Mar 04 '14 at 17:42
-
-
It doesn't work. I need fixed-point notation, not scientific notation. Once I do `s.setf(std::ios_base::fixed)`, I will get trailing zeroes. – Violet Giraffe Mar 05 '14 at 07:55