Я программирую дерево и в какой-то момент мне нужно поместить DBL_MAX (в качестве значения по умолчанию).
Я вижу правильное число, когда открываю сгенерированный xml-файл.
Но когда я использую ptree.get для получения номера, выдается исключение:conversion of data to type "d" failed
Вот мой код:
using boost::property_tree::ptree;
ptree pt;
double d=-DBL_MAX;
double d2=-1.797693134862316e+308;
double d3=-1.79769e+308;
cout<<d<<endl;
cout<<d2<<endl;
cout<<d3<<endl;
pt.put<double>("double", d);
write_xml("test.xml", pt);
cout << "totalEndTimeLowerBound: " << pt.get<double>("double")<<endl;
//doesn't work with d and d2, but works with d3
Что может вызвать эту ошибку и как я могу ее устранить?
По умолчанию, ptree
сохраняет свои значения как std::string
и конвертировать их, используя basic_stringstream
с точностью:
s.precision(std::numeric_limits<double>::digits10+1);
Эта проблема появляется при конвертации DBL_MAX
в std::string
потому что округляет число до недопустимого значения. Вы можете проверить это с помощью следующего кода:
ptree pt;
pt.put("min", -DBL_MAX);
pt.put("max", DBL_MAX);
cout << "Min=" << pt.get<string>("min") << std::endl;
cout << "Max=" << pt.get<string>("max") << std::endl;
Используя Visual Studio, он печатает:
Min = -1.797693134862316e + 308
Макс = 1,779693134862316e + 308
Тем не мение, DBL_MAX
определяется как 1.7976931348623158e+308
таким образом, напечатанное значение выходит за пределы.
Есть несколько обходных путей, но ни один не идеален:
DBL_MAX
, Например 1.797693134862315e+308
,bad_data
исключение и предположим, что это означает по умолчанию.Уменьшите точность сохраненного значения. Вы можете выполнить это, используя следующий код:
namespace boost { namespace property_tree
{
template <typename Ch, typename Traits>
struct customize_stream<Ch, Traits, double, void>
{
static void insert(std::basic_ostream<Ch, Traits>& s, const double& e) {
s.precision(std::numeric_limits<double>::digits10-1);
s << e;
}
static void extract(std::basic_istream<Ch, Traits>& s, double& e) {
s >> e;
if(!s.eof()) {
s >> std::ws;
}
}
};
}
Других решений пока нет …