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

4zcjmb1e  于 2023-04-01  发布在  其他
关注(0)|答案(6)|浏览(237)

如何在C++中将浮点数转换为字符串,同时指定精度和小数位数?
例如:3.14159265359 -> "3.14"

jw5wzhpr

jw5wzhpr1#

典型的方法是使用stringstream

#include <iomanip>
#include <sstream>

double pi = 3.14159265359;
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << pi;
std::string s = stream.str();

参见fixed

使用固定浮点表示法

str 流的floatfield标志设置为fixed
floatfield设置为fixed时,使用定点表示法写入浮点值:该值用与 *precision字段 *(precision)所指定的小数部分中的数字一样多的数字来表示,并且没有指数部分。
setprecision
对于技术目的的转换,例如将数据存储在XML或JSON文件中,C++17定义了to_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
}
hec6srdp

hec6srdp2#

做这类事情的习惯方法是“打印到字符串”。在C++中,这意味着使用std::stringstream如下:

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

x8goxv8g3#

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

#include <format>

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

或者来自the {fmt} librarystd::formatfmt::format函数基于(godbolt):

#include <fmt/core.h>

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

其中2是精度。
它不仅比使用iostreams或sprintf更短,而且速度明显更快,并且不受语言环境的影响。

pb3skfrl

pb3skfrl4#

另一个选项是snprintf

double pi = 3.1415926;

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

Demo。应添加错误处理,即检查written < 0

vi4fp9gy

vi4fp9gy5#

这里只使用std的解决方案。但是,请注意,这只是向下舍入。

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

代码将整个浮点数转换为字符串,但将“”后2个字符处的所有字符删除。

x3naxklr

x3naxklr6#

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

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的任何值,你将得到相同的打印输出。关键是避免方便的c11“to_string”函数。我花了一段时间才摆脱这个陷阱。最好的方法是stringstream和sprintf方法(C语言)。C11或更高版本应该提供第二个参数作为浮点数后的位数来显示。现在默认值是6。我这样做是为了让其他人不会在这个问题上浪费时间。
我写了我的第一个版本,请让我知道,如果你发现任何需要修复的bug。你可以控制与iomanipulator的确切行为。我的功能是显示小数点后的位数。

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

相关问题