将词法强制转换双倍提升为字符串,给出无效结果

boost lexical cast double to string giving invalid results

本文关键字:字符串 结果 无效 词法 转换      更新时间:2023-10-16

我正在尝试这个:

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

并期望输出为:

0.0009

但输出是:

0.00089999999999999998

g++ 版本: 5.4.0, 加速版本: 1.66

我能做些什么来让它打印它被给予的东西。

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

住在科里鲁

#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::(,也不灵活(现在所有双打都将以这种方式出现(。

真正的问题

问题是从十进制表示转换为二进制表示的精度损失。相反,请使用十进制浮点数表示形式:

住在科里鲁

#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
boost::lexical_cast 不允许

在将浮点数转换为其字符串表示形式时指定精度。从文档

对于更复杂的转换,例如精度或格式需要比默认行为lexical_cast提供的更严格的控制,建议使用传统的std::stringstream方法。

所以你可以使用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';

两者都将打印0.0009 .

0.0009是一个双精度浮动文本,假设IEEE754,值

0.00089999999999999997536692664112933925935067236423492431640625

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

0.00089999999999999998

真的,如果你想要精确的十进制精度,那么使用十进制类型(Boost 有一个(,或者自己在整数和拼接小数分隔符中。但在您的情况下,鉴于您只是输出数字而没有复杂的计算,四舍五入到第 15 个有效数字将产生预期的效果:注入

std::setprecision(15)

到输出流中。