Search code examples
xmllinqc#-4.0xpathxelement

XPath SUM function returning rounded result


The API I am using requires a hash which is comprised of the sum of the values of all specific elements. For example purposes assume it is the <long> elements in the sample XML.

When I calculate this value using XPath SUM function, I get a different value to that which I get when I simply iterate and add the nodes. Why is this?

string xml = @"
<longs>
    <long>10567823175596159</long>
    <long>10567823175596159</long>
</longs>
";

XDocument doc = XDocument.Parse(xml);

Console.WriteLine(long.Parse(doc.XPathEvaluate("sum(//longs/long/text())").ToString(), 
                            System.Globalization.NumberStyles.Float));

var accountNumbers = doc.XPathSelectElements("//longs/long");

long sum=0;
foreach (var accountnumber in accountNumbers)
{
    sum += long.Parse(accountnumber.Value);
}

Console.WriteLine(sum);

Output:

21135646351192300

21135646351192318

.Net Fiddle: https://dotnetfiddle.net/2niJ22


Solution

  • I think I found at least the reason for this behavior (even though not a real solution). If you just output the summed result to the console, without parsing, you'll see that it is

    Console.WriteLine(doc.XPathEvaluate("sum(//longs/long/text())"));
    2.11356463511923E+16
    

    Which is the scientific notation for "2.11356463511923 by (10 to the 16th power)". By moving the comma 16 figures to the right, the parsed number will be

    21135646351192300
    

    I guess that this is a limitation of the XPathEvaluate-Implementation. I would like to back this up but I couldnt find anything on the limits of this extension.

    If you really need this kind of precision (an error of 100 on 10 quadrillions is by any means negligeable) stick to the iterative approach.

    Anyway thanks for pointing this out, always good to know stuff like this!