Decimal points with std::stringstream?
Asked Answered
K

3

37

I have a bunch of integers that I put into stringstreams. Now I want to change the stringstreams into strings while keeping a constant precision with the strings. How would I do that? I know I can use stringstreams.precision(), but it's not working for some reason:

float a = 5.23;
float b = 3.134;
float c = 3.0;

std::stringstream ta;
std::stringstream tb;
std::stringstream tc;

ta << a;
tb << b;
tc << c;

ta.precision(2);
tb.precision(2);
tc.precision(2);

std::string out = "";
out += ta.str() + "\n";
out += tb.str() + "\n";
out += tc.str() + "\n";

Will return 5.23\n3.134\n3.0, rather than 5.23\n3.13\n3.00

Kierkegaard answered 25/2, 2011 at 3:17 Comment(0)
B
60

I think that your problem is that precision() sets the precision used in future stream insertion operations, not when generating the final string to present. That is, by writing

ta << a;
tb << b;
tc << c;

ta.precision(2);
tb.precision(2);
tc.precision(2);

You're setting precision too late, as the first three lines have already converted the floating point numbers to strings using the default precision.

To fix this, try changing the order in which you execute these statements to

ta.precision(2);
tb.precision(2);
tc.precision(2);

ta << a;
tb << b;
tc << c;

This will cause the writes into the stringstream to use your custom precision rather than the existing defaults.

However, the effect of the precision modifier is only meaningful if you explicitly tell the stream that you want to use either fixed-precision or scientific notation for output. To do this, you can use either the fixed or scientific modifiers:

ta.precision(2);
tb.precision(2);
tc.precision(2);

ta << fixed << a;
tb << fixed << b;
tc << fixed << c;

This will correctly display the appropriate number of digits.

On a related note, you don't need to use three stringstreams to accomplish your goal. You can just use one:

std::stringstream t;
t.precision(2);

t << fixed << a << '\n' << b << '\n' << c << '\n';

std::string out = t.str();
Bottom answered 25/2, 2011 at 3:21 Comment(6)
thanks, but its not working. im still getting 3.0 rather than 3.00Kierkegaard
@noobcpp- Whoops! My mistake. I just updated this to mention that you need to use either fixed or scientific mode on the stringstreams. Try making that change and see if it fixes things.Bottom
+1. @noobcpp: Also, check out: cplusplus.com/reference/iostream/ios_base/precision (though they say to use 0 in a place that is giving me a compiler error).Phatic
You don't need to split out the precision call on a separate line: t << setprecision(2) << fixed << a ...Shack
2 years later, and this post is still saving lives! Thanks @BottomArni
example: #include <iostream> #include <sstream> #include <iomanip> std::stringstream ss; ss << std::setprecision(2) << std::fixed << my_float; std::cout << ss.str() << std::endl;Pisa
C
8

In C++20 you can use std::format which is move efficient and less verbose than std::stringstream:

float a = 5.23;
float b = 3.134;
float c = 3.0;
std::string out = std::format("{:.2f}\n{:.2f}\n{:.2f}\n", a, b, c);

In the meantime you can use the {fmt} library, std::format is based on (godbolt).

Disclaimer: I'm the author of {fmt} and C++20 std::format.

Chivalric answered 3/3, 2021 at 4:7 Comment(0)
R
1

You need to set fixed as well as precision before feeding the data to the stringstream. Here's a working example of what you intended to do:

#include <iostream>
#include <sstream>

using namespace std;

int main(){
    float a = 5.23;
    float b = 3.134;
    float c = 3.0;

    std::stringstream ss;
    ss.setf(std::ios::fixed);
    ss.precision(2);
    
    ss << a << "\n";
    ss << b << "\n";
    ss << c << "\n";
    cout<<ss.str()<<endl;

    return 0;
}

output:

5.23
3.13
3.00
Recti answered 29/10, 2022 at 14:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.