kewlnamehuh / pugixml

Automatically exported from code.google.com/p/pugixml
0 stars 0 forks source link

Insufficient precision for double values #230

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?

Storing double values with high precision fails due to insufficient storage 
precision in set_value_convert function.

What is the expected output? What do you see instead?

We are using double values with high precision requirements. These gets rounded 
well below double precision limits, due to limited value numbers in conversion 
to char array format.

Which version of pugixml are you using? On what operating system/compiler?

PugiXML 1.4 compiled with Visual Studio 2010 and Visual Studio 2013. 

Proposed solution:
We changed the set_value_convert function for double into:

PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t 
header_mask, double value)
{
    char buf[128];
    sprintf(buf, "%.17g", value);
    return set_value_buffer(dest, header, header_mask, buf);
}

Original issue reported on code.google.com by bjorn.bl...@gmail.com on 19 May 2014 at 12:51

GoogleCodeExporter commented 9 years ago
The following piece of code shows the missing precision clearly:
    double valueBefore = 100000.0/3.0;
    printf ("Before:\n");
    printf ("Double (%%g): %g\n", valueBefore); // Use the shortest representation
    printf ("Double (%%.16g): %.16g\n", valueBefore); // Use the shortest representation 16 number of digits
    printf ("Double (%%.17g): %.17g\n", valueBefore); // Use the shortest representation 17 number of digits
    printf ("Double (%%.18g): %.18g\n", valueBefore); // Use the shortest representation 18 number of digits

    pugi::xml_document doc;
    pugi::xml_node testNode = doc.append_child("node");
    testNode.append_attribute("value") = valueBefore;
    double valueAfter = testNode.attribute("value").as_double(0.0);

    printf ("After:\n");
    printf ("Double (%%g): %g\n", valueAfter); // Use the shortest representation
    printf ("Double (%%.16g): %.16g\n", valueAfter); // Use the shortest representation 16 number of digits
    printf ("Double (%%.17g): %.17g\n", valueAfter); // Use the shortest representation 17 number of digits
    printf ("Double (%%.18g): %.18g\n", valueAfter); // Use the shortest representation 18 number of digits

It will produce the following output:
Before:
Double (%g): 33333.3
Double (%.16g): 33333.33333333334
Double (%.17g): 33333.333333333336
Double (%.18g): 33333.333333333336
After:
Double (%g): 33333.3
Double (%.16g): 33333.3
Double (%.17g): 33333.300000000003
Double (%.18g): 33333.300000000003

Original comment by bjorn.bl...@gmail.com on 19 May 2014 at 2:05

GoogleCodeExporter commented 9 years ago

Original comment by arseny.k...@gmail.com on 27 Sep 2014 at 4:51

GoogleCodeExporter commented 9 years ago
This issue was moved to GitHub: https://github.com/zeux/pugixml/issues/18

Original comment by arseny.k...@gmail.com on 26 Oct 2014 at 9:14