1

I have noticed something strange. This is my XML

<Items>
    <Item>
        <Name>A</Name>
        <Amount>0.0012</Amount>
        <Quantity>17</Quantity>
        <TotalAmount>0.0204</TotalAmount>
    </Item>
    <Item>
        <Name>B</Name>
        <Amount>1</Amount>
        <Quantity>2</Quantity>
        <TotalAmount>2</TotalAmount>
    </Item>
    <Item>
        <Name>C</Name>
        <Amount>3</Amount>
        <Quantity>2</Quantity>
        <TotalAmount>6</TotalAmount>
    </Item>
</Items>

And this is the XPath that I used

/Items/Item[((Amount * Quantity) != TotalAmount)]/Name

This XPath had to print the name of the item whose TotalAmount!= Product(Amount, Quantity).

I get the value A. But I do not understand why this is happening Because 0.0012 * 17 = 0.0204

And if I remove Item 'A', then I do not get a result.

The same goes for newer versions of XPath as well

for $x in /Items/Item[((Amount * Quantity) != TotalAmount)] return $x/Name

I'm using Saxon 9 in Java.

Can someone explain why this is happening.

1 Answer 1

1

Try using xs:decimal/xs:integer for better precision: /Items/Item[((xs:decimal(Amount) * xs:integer(Quantity)) != TotalAmount)]/Name.

If you look at http://xsltransform.net/94AbWBV which does

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs">

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:template match="/">
      <results>
          <names-precise>
            <xsl:value-of select="/Items/Item[((xs:decimal(Amount) * xs:integer(Quantity)) != TotalAmount)]/Name"/>
          </names-precise>
          <names-imprecise>
              <xsl:value-of select="/Items/Item[((Amount * Quantity) != TotalAmount)]/Name"/>
          </names-imprecise>
          <xsl:apply-templates/>
      </results>

    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Item">
        <xsl:copy>
            <xsl:apply-templates/>
            <double-computation>
                <xsl:value-of select="Amount * Quantity"/>
            </double-computation>
            <decimal-computation>
                <xsl:value-of select="xs:decimal(Amount) * xs:integer(Quantity)"/>
            </decimal-computation>
        </xsl:copy>
    </xsl:template>
</xsl:transform>

you can see that the default floating point arithmetic used does not suffice to compute the exact result:

<results>
   <names-precise/>
   <names-imprecise>A</names-imprecise>
   <Items>
      <Item>
         <Name>A</Name>
         <Amount>0.0012</Amount>
         <Quantity>17</Quantity>
         <TotalAmount>0.0204</TotalAmount>
         <double-computation>0.020399999999999998</double-computation>
         <decimal-computation>0.0204</decimal-computation>
      </Item>
      <Item>
         <Name>B</Name>
         <Amount>1</Amount>
         <Quantity>2</Quantity>
         <TotalAmount>2</TotalAmount>
         <double-computation>2</double-computation>
         <decimal-computation>2</decimal-computation>
      </Item>
      <Item>
         <Name>C</Name>
         <Amount>3</Amount>
         <Quantity>2</Quantity>
         <TotalAmount>6</TotalAmount>
         <double-computation>6</double-computation>
         <decimal-computation>6</decimal-computation>
      </Item>
   </Items>
</results>

The same imprecision exists in other language like Javascript using the IEEE double number format:

document.getElementById('result').textContent = 0.0012 * 17;
<p>Result of <code>0.0012 * 17</code> with Javascript is <code id="result"></code>.</p>

Sign up to request clarification or add additional context in comments.

1 Comment

Hi Martin. Thanks. Works like charm. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.