将 lexical_cast double 提升为字符串,给出无效结果

boost lexical cast double to string giving invalid results

我正在尝试这个:

std::cout << boost::lexical_cast<std::string>(0.0009) << std::endl;

并期望输出为:

0.0009

但输出是:

0.00089999999999999998

g++版本:5.4.0,Boost版本:1.66

我该怎么做才能让它打印出给定的内容。

boost::lexical_cast 不允许您在将浮点数转换为其字符串表示形式时指定精度。来自 documentation

For more involved conversions, such as where precision or formatting need tighter control than is offered by the default behavior of lexical_cast, the conventional std::stringstream approach is recommended.

所以你可以使用 stringstream

double d = 0.0009;
std::ostringstream ss;
ss << std::setprecision(4) << d;
std::cout << ss.str() << '\n';

或者另一种选择是使用 boost::format 库。

std::string s = (boost::format("%1$.4f") % d).str();
std::cout << s << '\n';

Both will print 0.0009.

0.0009 是双精度浮点文字,假设 IEEE754,值

0.00089999999999999997536692664112933925935067236423492431640625

这就是 boost::lexical_cast<std::string> 所看到的函数参数。 cout 格式化程序中的默认精度设置四舍五入到第 17 位有效数字:

0.00089999999999999998

真的,如果你想要精确的 decimal 精度,那么使用 decimal 类型(Boost 有一个),或者使用整数并自己拼接小数分隔符。但在你的情况下,假设你只是输出没有复杂计算的数字,四舍五入到第 15 位有效数字将产生预期的效果: inject

std::setprecision(15)

进入输出流。

可以 实际上覆盖默认精度:

Live On Coliru

#include <boost/lexical_cast.hpp>

#ifdef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
#    error unsupported
#endif

template <> struct boost::detail::lcast_precision<double> : std::integral_constant<unsigned, 5> { };

#include <string>
#include <iostream>

int main() {
    std::cout << boost::lexical_cast<std::string>(0.0009) << std::endl;
}

版画

0.0009

但是,这既不受支持 (detail::) 又不灵活(现在所有双打都会以这种方式出现)。

真正的问题

问题是从十进制表示形式转换为二进制表示形式时精度下降。相反,使用十进制浮点数表示:

Live On Coliru

#include <boost/lexical_cast.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <string>
#include <iostream>

using Double = boost::multiprecision::cpp_dec_float_50;

int main() {
    Double x("0.009"),
           y = x*2,
           z = x/77;

    for (Double v : { x, y, z }) {
        std::cout << boost::lexical_cast<std::string>(v) << "\n";
        std::cout << v << "\n";
    }
}

版画

0.009
0.009
0.018
0.018
0.000116883
0.000116883