I am working with the JSON-C Library v0.11 to output JSON. I have a string of doubles in a char * that I need to output as an array.
I have: const char* doubles = "0.1234, 0.5678, 1.1234, 1.5678";
I want to output:
"doubles", [0.1234, 0.5678, 1.1234, 1.5678]
My issue is that the JSON-C library when using json_object_new_double
adds trailing zeroes and I want my doubles to be exact.
Is there a workaround to this?
char *token = strtok(doubles, ",");
while (token != NULL) {
double current = atof(token);
json_object_array_add(my_array, json_object_new_double(current));
token = strtok(NULL, ",");
}
// Add the key-value pair as an array
json_object_object_add(root_obj, "my_array", my_array);
The json-c library uses
snprintf
with a format"%.17g"
to convert thedouble
values as strings for output. This produces an accurate conversion such that any 2 differentdouble
values produce different output and converting back this output produces the originaldouble
value. Javascript interpreters use more sophisticated logic to produce minimal strings when converting numbers to strings. The library should use that too, but it seems the authors are not aware of the issue. They do however provide a hack to modify the conversion behavior:json_c_set_serialization_double_format
.There is no exact binary representation of
0.5678
as adouble
in the ubiquitous IEEE binary 64 bit format used in most systems. The closestdouble
value in this format is 5114287736841935 * 2-53 whose exact decimal representation is0.56779999999999997140065488565596751868724822998046875
(and0x1.22b6ae7d566cfp-1
in hexadecimal floating point format). If you convert this value to decimal with 4 to 16 decimal places, the conversion produces0.5678
, but the library uses 17 places to ensure that alldouble
values produce different output, so on your system, the string produced by the library is0.56779999999999997
, yetatof("0.56779999999999997")
andatof("0.5678")
should produce the samedouble
value.To avoid this problem, you would need to use decimal floats, which json-c does not seem to support or a way to specify the maximum number of decimals in the conversion to string operated by json-c, and the package does provide an API to specify a conversion format:
json_c_set_serialization_double_format
in the current version 0.17, much more recent than your old 0.11 version.Here are my recommendations:
double
values as they will convert back to the samedouble
value upon reading in the destination system.json_c_set_serialization_double_format
to specify a conversion format that produces the expected output.