views:

242

answers:

3

I have this XML data and try and make a sum of it using the XSLT snippet below.

Xml

<?xml version="1.0" encoding="utf-8"?>
<values>
    <value>159.14</value>
    <value>-2572.50</value>
    <value>-2572.50</value>
    <value>2572.50</value>
    <value>2572.50</value>
    <value>-159.14</value>
</values>

Xslt

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;

<xsl:template match="/">
    <xsl:value-of select="sum(values/value)"/>
</xsl:template>

</xsl:stylesheet>

In my world the value should then be 0 but it ends up being -0.0000000000005684341886080801

Run it in Visual Studio and see for yourself. Why? is this happening?

+1  A: 

How about adding round?

round(sum(values/value))
S.Mark
Sure that solves it - but why is it happening?
Riri
Posted the same comment above, but it feels in place here as well. Just to add a little completeness to the solution given below below and answer your question of "Why?" Check out "What Every Computer Scientist should know about Floating-Point Arithmetic" http://docs.sun.com/source/806-3568/ncg%5Fgoldberg.html
LorenVS
+4  A: 

Seems your XSLT processor convert decimal numbers strings to float-point precision numbers before sum;

Well, you can always to use round function and divide by your desired precision or to use format-number function, if available:

<xsl:template match="/">
    <xsl:value-of select="round(sum(values/value)) div 100"/><br />
    <xsl:value-of select="format-number(sum(values/value), '0.00')"/>
</xsl:template>
Rubens Farias
@Riri: If you are surprised about this behavior, I think this: http://stackoverflow.com/questions/249467/what-is-a-simple-example-of-floating-point-rounding-error and the linked page in the accepted answer is worth a read.
Tomalak
A: 

That only accomplishes a rounded total, while fractions of a cent add up to large amounts of money in big invoices. In my example I have a difference of 0.04999999923 in a total of 195,259.90. Like in the film Office Space, where 3 men corrupt bank software to get such fractions of amounts onto their account, building up a huge amount of money. :)

Anybody got a XSL/T 1.0 solution for correcting this?

It turned out I was wrong. I checked my results against Excel, but it created to small columns so I saw 195,259.9. Later, when I got 195,260 from a Sum of two cells that just wasn't right, I discovered this. So beware of this (it took me several hours).

In my case, the result is .00000000077 less than expected over 1216 rows of data and a total of almost 200,000. So, only if you're dealing with trillions or so this would be a problem ;)

E. Zeelen