How do you convert a float to a string in C++ while specifying the precision & number of decimal digits?
For example: 3.14159265359 -> "3.14"
How do you convert a float to a string in C++ while specifying the precision & number of decimal digits?
For example: 3.14159265359 -> "3.14"
A typical way would be to use stringstream:
#include <iomanip>
#include <sstream>
double pi = 3.14159265359;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << pi;
std::string s = stream.str();
See fixed
Use fixed floating-point notation
Sets the
floatfieldformat flag for the str stream tofixed.When
floatfieldis set tofixed, floating-point values are written using fixed-point notation: the value is represented with exactly as many digits in the decimal part as specified by the precision field (precision) and with no exponent part.
and setprecision.
For conversions of technical purpose, like storing data in XML or JSON file, C++17 defines to_chars family of functions.
Assuming a compliant compiler (which we lack at the time of writing), something like this can be considered:
#include <array>
#include <charconv>
double pi = 3.14159265359;
std::array<char, 128> buffer;
auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), pi,
std::chars_format::fixed, 2);
if (ec == std::errc{}) {
std::string s(buffer.data(), ptr);
// ....
}
else {
// error handling
}
You can use C++20 std::format:
#include <format>
int main() {
std::string s = std::format("{:.2f}", 3.14159265359); // s == "3.14"
}
or the fmt::format function from the {fmt} library, std::format is based on (godbolt):
#include <fmt/core.h>
int main() {
std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14"
}
where 2 is a precision.
It is not only shorter than using iostreams or sprintf but also significantly faster and is not affected by the locale.
Disclaimer: I'm the author of {fmt} and C++20 std::format.
std::format("{:.2f}", 3 / 2) it won't compile with call to immediate function is not a constant expression. Why?.2f is an invalid format specifier for an integer. You probably want to use floating point instead.std::setprecision(), I'm moving to C++20.Here a solution using only std. However, note that this only rounds down.
float number = 3.14159;
std::string num_text = std::to_string(number);
std::string rounded = num_text.substr(0, num_text.find(".")+3);
For rounded it yields:
3.14
The code converts the whole float to string, but cuts all characters 2 chars after the "."
number + 0.005 in my case.Another option is snprintf:
double pi = 3.1415926;
std::string s(16, '\0');
auto written = std::snprintf(&s[0], s.size(), "%.2f", pi);
s.resize(written);
Demo. Error handling should be added, i.e. checking for written < 0.
snprintf be better in this case? Please explain... It certainly won't be faster, produce less code [I have written a printf implementation, it's fairly compact at just under 2000 lines of code, but with macro expansions gets to around 2500 lines]Here I am providing a negative example where your want to avoid when converting floating number to strings.
float num=99.463;
float tmp1=round(num*1000);
float tmp2=tmp1/1000;
cout << tmp1 << " " << tmp2 << " " << to_string(tmp2) << endl;
You get
99463 99.463 99.462997
Note: the num variable can be any value close to 99.463, you will get the same print out. The point is to avoid the convenient c++11 "to_string" function. It took me a while to get out this trap. The best way is the stringstream and sprintf methods (C language). C++11 or newer should provided a second parameter as the number of digits after the floating point to show. Right now the default is 6. I am positing this so that others won't wast time on this subject.
I wrote my first version, please let me know if you find any bug that needs to be fixed. You can control the exact behavior with the iomanipulator. My function is for showing the number of digits after the decimal point.
string ftos(float f, int nd) {
ostringstream ostr;
int tens = stoi("1" + string(nd, '0'));
ostr << round(f*tens)/tens;
return ostr.str();
}
You can use fmt library.
3.14159265359 -> "3.14"
#include <fmt/format.h>
#include <string>
double pi = 3.14159265359;
std::string st = fmt::format("pi = {:.2f}", pi);
printf family functions while retaining the type-safe of std::cout while getting a huge speed boost compared to the latter. I'd like to refer reader to the documentation of fmt to learn more about it. For those who have access to C++20 library, you can use std::print which uses fmt as the reference implementation.Using nothing but std:
float number = 3.14159265359;
int precision = 2;
std::string rounded = std::to_string(
std::round(number * std::pow(10, precision)) /
std::pow(10, precision)).substr(
0, std::to_string(
std::round(number * std::pow(10, precision)) /
std::pow(10, precision)).find(".") + precision + 1);