It is actually an issue of floating point number parsing/printing implementation. Although floating point numbers can only represent some decimal numbers exactly (0.25 is one of ~2^64), it is necessary to parse a string representation to the nearest binary representation. When printing floating point, it is also necessary to print the (preferably the shortest) string representation which can be restored to the binary representation.
I admit that I had not investigate JsonCPP to see if there is a solution for this. But as I am the author of RapidJSON, I tried to see how RapidJSON performs for this:
const char json[] =
"{"
"\"MinXValue\": 0.1,"
"\"MaxXValue\": 0.15,"
"\"MinYValue\": 0.25,"
"\"MaxYValue\": 1.1,"
"\"MinObjectSizeValue\": 1"
"}";
using namespace rapidjson;
Document d;
d.Parse(json);
StringBuffer sb;
PrettyWriter<StringBuffer> writer(sb);
d.Accept(writer);
std::cout << sb.GetString();
And the result:
{
"MinXValue": 0.1,
"MaxXValue": 0.15,
"MinYValue": 0.25,
"MaxYValue": 1.1,
"MinObjectSizeValue": 1
}
RapidJSON implemented both parsing and printing algorithms internally. Normal precision parsing will have maximum 3 ULP errors, but with full precision parsing flag (kParseFullPrecisionFlag
) it can always parse to nearest representation. The printing part implemented Grisu2 algorithm. It does always generate an exact result, and more than 99% of time to be shortest (optimal).
Actually, using strtod()
and sprintf(..., "%.17g", ...)
can solve this problem too. But they are much slower in current C/C++ standard library. For example, I have done a benchmark for printing double
. So in RapidJSON we implemented its own optimized header-only solutions.