如何将boost::multiprecision::cpp_dec_float_100转为指定精度的字符串?
Boost.Multiprecision 精度格式化问题解决方案
问题描述
我需要实现一个基于boost::multiprecision::cpp_dec_float_100执行计算并返回指定精度字符串结果的函数,但遇到精度设置问题:
- 指定精度为9时,数值
2345.12345678910111213期望得到"2345.123456789",实际却得到"12345.1235"; - 数值
1.12345678910111213期望得到"1.123456789",实际得到"1.12345679"。
已知可通过std::stringstream配合std::fixed与std::setprecision实现,或对字符串进行截取处理,但想了解Boost是否提供更简便的原生方法。
测试代码:
#include <iostream> #include <boost/multiprecision/cpp_dec_float.hpp> namespace bmp = boost::multiprecision; std::string foo_1() { bmp::cpp_dec_float_100 val{"12345.12345678910111213"}; return val.str(9); } std::string foo_2() { bmp::cpp_dec_float_100 val{"1.12345678910111213"}; return val.str(9); } int main() { auto const val_1 = foo_1(); auto const val_2 = foo_2(); std::cout << "val_1: " << val_1 << std::endl; std::cout << "val_2: " << val_2 << std::endl; return 0; }
问题原因
cpp_dec_float_100的str(n)方法中,参数n指的是有效数字位数,而非小数点后的位数。这就是结果不符的核心原因:
- 对于
12345.12345678910111213,9位有效数字会保留到小数点后第4位(12345.1235); - 对于
1.12345678910111213,9位有效数字会保留到小数点后第8位(1.12345679),且自动四舍五入。
Boost原生解决方案
Boost.Multiprecision提供了直接控制小数点后位数的原生格式化方式,无需额外字符串处理或标准库流操作。
方法1:使用带格式标志的str重载
调用str方法时传入std::ios_base::fixed格式标志和精度值,即可指定小数点后的位数:
#include <iostream> #include <boost/multiprecision/cpp_dec_float.hpp> namespace bmp = boost::multiprecision; std::string foo_1() { bmp::cpp_dec_float_100 val{"12345.12345678910111213"}; return val.str(std::ios_base::fixed, 9); // 指定fixed格式,小数点后9位 } std::string foo_2() { bmp::cpp_dec_float_100 val{"1.12345678910111213"}; return val.str(std::ios_base::fixed, 9); } int main() { auto const val_1 = foo_1(); auto const val_2 = foo_2(); std::cout << "val_1: " << val_1 << std::endl; // 输出2345.123456789 std::cout << "val_2: " << val_2 << std::endl; // 输出1.123456789 return 0; }
方法2:使用boost::multiprecision::set_precision(灵活格式控制)
如果需要更复杂的格式组合,可以结合std::stringstream和Boost提供的精度控制工具,这也是Boost原生的方案:
#include <iostream> #include <sstream> #include <boost/multiprecision/cpp_dec_float.hpp> #include <boost/multiprecision/number.hpp> namespace bmp = boost::multiprecision; std::string format_value(const bmp::cpp_dec_float_100& val, int decimal_places) { std::stringstream ss; ss << std::fixed << bmp::set_precision(decimal_places) << val; return ss.str(); } std::string foo_1() { bmp::cpp_dec_float_100 val{"12345.12345678910111213"}; return format_value(val, 9); } std::string foo_2() { bmp::cpp_dec_float_100 val{"1.12345678910111213"}; return format_value(val, 9); }
说明
str(std::ios_base::fixed, n)中的n直接对应小数点后的位数,完全匹配需求;- 该方式无需手动处理字符串,是Boost原生的简便解决方案,避免了标准库流的额外代码开销。
内容的提问来源于stack exchange,提问作者bladzio
相关产品推荐
相关产品推荐

