Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XPath outputs .07 * 100 * 100 as 700.00000000000011 why?

I have noticed some strange precision behaviour that I cannot understand, I have some XML:

<CLD>
    <UCRV>
        <UCR1>.07</UCR1>
    </UCRV>
</CLD>

And in an XSLT file, I am selecting the value as pence (or 100 pence as it seems, I don't know why but it's what the customer wants!) as:

<xsl:value-of select="./s0:CLD/s0:UCRV/s0:UCR1/text() * 100 * 100"/>

But this is output as 700.00000000000011 The data type is xsd:Decimal. Is there some default precisioning going on here? I can simply round the number but I just wanted to understand it a bit better.

Thanks

like image 469
Rodders Avatar asked Sep 18 '12 10:09

Rodders


3 Answers

Floating point numbers can't represent everything precisely. Since the numbers are stored in binary form, numbers that seem to be easy to write in decimal can be actually only approached in binary sometimes. This is the case with 0.07, it's stored internally as 0.070000000000000011 as it seems in your case. As a rule of thumb, you should never trust floating point values so as to compare them directly without rounding.

like image 161
ggPeti Avatar answered Oct 20 '22 12:10

ggPeti


As people already explained, the only numeric type used in XPath is xs:double.

The number() function converts a value to a double. Therefore, operations on numbers in XPath 1.0 can and sometimes do lead to loss of precision.

There exist different solutions:

  1. Use the round() function. One can also use the floor() or the ceiling() functions.

  2. Use the XSLT format-number() function() or the <xsl:number> instruction.

Do note that XPath 2.0 supports all XSD numeric types, including xs:decimal. An XPath 2.0 expression that doesn't cause loss of precision is:

xs:decimal(0.07)*100*100
like image 37
Dimitre Novatchev Avatar answered Oct 20 '22 13:10

Dimitre Novatchev


This is standard floating point maths. In this there is a maximun number of bits to fit the number and the number is held in scientific form in binary. Here 0.07 cannot be represented exactly and is held as 0.070000000000000011.

For more see many questions on SO (albeit in other languages) using tag floating-point, wikipedia and What Every Computer Scientist Should Know About Floating-Point Arithmetic

like image 39
mmmmmm Avatar answered Oct 20 '22 12:10

mmmmmm