I am trying this:
std::cout << boost::lexical_cast<std::string>(0.0009) << std::endl;
and expecting the output to be:
0.0009
But the output is:
0.00089999999999999998
g++ version: 5.4.0, Boost version: 1.66
What can I do to make it print what it's been given.
答案 0 :(得分:3)
boost::lexical_cast
doesn't allow you to specify the precision when converting a floating point number into its string representation. From the 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 conventionalstd::stringstream
approach is recommended.
So you could use stringstream
double d = 0.0009;
std::ostringstream ss;
ss << std::setprecision(4) << d;
std::cout << ss.str() << '\n';
Or another option is to use the boost::format
library.
std::string s = (boost::format("%1$.4f") % d).str();
std::cout << s << '\n';
答案 1 :(得分:2)
0.0009
is a double precision floating literal with, assuming IEEE754, the value
0.00089999999999999997536692664112933925935067236423492431640625
That's what boost::lexical_cast<std::string>
sees as the function parameter. And the default precision setting in the cout
formatter is rounding to the 17th significant figure:
0.00089999999999999998
Really, if you want exact decimal precision, then use a decimal type (Boost has one), or work in integers and splice in the decimal separator yourself. But in your case, given that you're simply outputting the number with no complex calculations, rounding to the 15th significant figure will have the desired effect: inject
std::setprecision(15)
into the output stream.
答案 2 :(得分:2)
您可以实际上覆盖默认精度:
<强> 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