我想替换对 boost::lexical_cast<std::string>(d)
的调用解决方案:
- 不使用语言环境(我怀疑这是多线程应用程序运行缓慢的原因),
- 保留与
lexical_cast
相同的输出.
我正在使用用 Boost.Spirit.Karma 编写的生成器(因为它更快)。但是改了之后结果不一样了,因为Karma有自己的方式来显示double
的小数部分
我知道在某种程度上可以控制 double
带有策略的生成器,但我的尝试失败了。我能想到的最好的办法就是这个生成器定制和这个测试程序:
#include <limits>
#include <string>
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <boost/spirit/include/karma.hpp>
namespace karma = boost::spirit::karma;
template <typename Num>
struct fp_policy : karma::real_policies<Num>
{
template <typename OutputIterator>
static bool dot (OutputIterator& sink, Num n, unsigned /*precision*/)
{
if (n)
return karma::char_inserter<>::call(sink, '.'); // generate the dot by default
else
return false;
}
static unsigned precision(Num)
{
return 15;
}
};
karma::real_generator<double, fp_policy<double>> const fp_generator {};
std::string karma_to_string(double const& v)
{
std::string ans;
std::back_insert_iterator<std::string> sink {ans};
(void)karma::generate(sink, fp_generator, v);
return ans;
}
void test_number (double x)
{
std::cout << "stream: " << x << "\n";
std::cout << "lexiical_cast: " << boost::lexical_cast<std::string>(x) << "\n";
std::cout << "spirit: " << karma_to_string(x) << "\n";
std::cout << "--------------------------------------------" << std::endl;
}
int main()
{
test_number(0.45359237);
test_number(111.11);
test_number(1.0);
test_number(3.25);
}
它给出了以下输出:
stream: 0.453592
lexiical_cast: 0.45359237000000002
spirit: 0.45359237
--------------------------------------------
stream: 111.11
lexiical_cast: 111.11
spirit: 111.109999999999999
--------------------------------------------
stream: 1
lexiical_cast: 1
spirit: 1
--------------------------------------------
stream: 3.25
lexiical_cast: 3.25
spirit: 3.25
--------------------------------------------
如您所见,两者之间存在明显差异。如果我使用默认的 double 生成器 ( karma::double_
),结果仍然会有所不同,但在不同的地方:
stream: 0.453592
lexiical_cast: 0.45359237000000002
spirit: 0.454
--------------------------------------------
stream: 111.11
lexiical_cast: 111.11
spirit: 111.11
--------------------------------------------
stream: 1
lexiical_cast: 1
spirit: 1.0
--------------------------------------------
stream: 3.25
lexiical_cast: 3.25
spirit: 3.25
--------------------------------------------
我的问题:如何为 double
配置生成器s(或者甚至可能吗?)以便输出更接近基于流的转换器?
最佳答案
我会创建一个基于 sprintf
的生成器,就像我在此处进行的逆向工程一样:
That answer comes with a full test-suite to verify "lexical-cast compliance" for values including NaN, positive/negative zero and infinities.
如果你愿意,我可以想出一个演示。到目前为止,最简单的做法似乎是将值包装在具有重载输出流操作的类型中,以便 boost::spirit::karma::stream
directive可以使用。
或者,您可以创建自定义生成器类型(满足 concept requirements )。
关于c++ - 如何使用 Boost.Spirit 在 C++ 中序列化一个 double,以便输出接近标准流的输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49432988/