将浮点数转换为具有指定精度和小数位数的字符串?

如何在 C + + 中将浮点数转换为字符串,同时指定十进制数的精度和数目?

For example: 3.14159265359 -> "3.14"

191911 次浏览

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 修好了

使用固定浮点表示法

STR流的 floatfield格式标志设置为 fixed

floatfield设置为 fixed时,浮点值使用定点表示法写入: 该值在小数部分用与 精密场(precision)指定的一样多的数字表示,没有指数部分。

设定精度


对于 技术用途转换,就像在 XML 或 JSON 文件中存储数据一样,C + + 17定义了 到 _ chars函数族。

假设有一个顺从的编译器(我们在编写本文时缺乏这种编译器) , 这样的事情可以被认为是:

#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
}

做这类事情的通常方法是“打印到字符串”。在 C + + 中,这意味着使用 std::stringstream类似于:

std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
std::string mystring = ss.str();

另一个选择是 snprintf:

double pi = 3.1415926;


std::string s(16, '\0');
auto written = std::snprintf(&s[0], s.size(), "%.2f", pi);
s.resize(written);

演示 。应该添加错误处理,即检查 written < 0

在这里,我提供了一个负面的例子,你想避免时,转换浮动数字字符串。

float num=99.463;
float tmp1=round(num*1000);
float tmp2=tmp1/1000;
cout << tmp1 << " " << tmp2 << " " << to_string(tmp2) << endl;

你得到了

99463 99.463 99.462997

注意: num 变量可以是任何接近99.463的值,你会得到相同的打印出来。关键是要避免使用方便的 c + + 11“ to _ string”函数。我花了很长时间才走出这个陷阱。最好的方法是 stringstream 和 sprintf 方法(C 语言)。C + + 11或更高版本应该提供第二个参数作为浮点数后面要显示的位数。现在默认值是6。我提出这个假设是为了让其他人不要在这个问题上浪费时间。

我写了我的第一个版本,请让我知道,如果你发现任何错误,需要修复。你可以用操纵器控制精确的行为。我的函数是用来显示小数点后的位数。

string ftos(float f, int nd) {
ostringstream ostr;
int tens = stoi("1" + string(nd, '0'));
ostr << round(f*tens)/tens;
return ostr.str();
}

你可以使用 C + + 20 std::format:

#include <format>


int main() {
std::string s = std::format("{:.2f}", 3.14159265359); // s == "3.14"
}

{ fmt }库fmt::format功能,std::format是基于(Godbolt) :

#include <fmt/core.h>


int main() {
std::string s = fmt::format("{:.2f}", 3.14159265359); // s == "3.14"
}

其中 2是一个精度。

它不仅比使用 iostream 或 sprintf短,而且也比使用 significantly faster短,不受现场影响。

这里的解决方案只使用标准。但是,请注意,这只是四舍五入。

    float number = 3.14159;
std::string num_text = std::to_string(number);
std::string rounded = num_text.substr(0, num_text.find(".")+3);

rounded而言,其收益率为:

3.14

该代码将整个 float 转换为 string,但是在“”之后将所有字符删除2个字符