In XQuery when I am trying to execute the below function,
fn:number('10.12')
the result is 10.12 but if I try to typecast it into decimal,
xs:decimal(fn:number('10.12'))
the result is 10.1199999999999992184029906638897955417633056640625
Can anyone help me understand what is the reason behind this.
fn:number()
is defined to return an xs:double
, that is a 64-bit IEEE floating point number. There is no xs:double
that is exactly equal to the decimal value 10.12
: the only numbers that can be exactly represented are those of the form m × 2^e , where m is an integer whose absolute value is less than 253, and e is an integer between −1074 and 971, inclusive. So you get an approximation.
XQuery defines the rules for converting a string to xs:double
by reference to the rules in XML Schema (XSD) (either version 1.0 or 1.1 at implementor discretion). XSD 1.0 required the results to be consistent with the algorithm published at
William D Clinger. How to Read Floating Point Numbers Accurately. In Proceedings of Conference on Programming Language Design and Implementation, pages 92-101. Available at: ftp://ftp.ccs.neu.edu/pub/people/will/howtoread.ps
XSD 1.1 is a bit more liberal.
But either way, you will get an xs:double
that is not exactly equal to 10.12.
If you converted the resulting xs:double
to a string, the chances are that it would be output as 10.12
, because the processor is allowed to generate any string that round-trips back to the supplied xs:double
[Note 1]. But if you convert it to an xs:decimal
, the rules say that you get "the xs:decimal
value, within the set of xs:decimal
values that the implementation is capable of representing, that is numerically closest to [the supplied value]". Which won't be exactly 10.12
.
As it happens, there's a community group working on XQuery 4.0 and its agenda includes a proposal to change the rules so double-to-decimal conversion follows the same rules as double-to-string conversion: see https://github.com/qt4cg/qtspecs/issues/410
[Note 1] That's effectively what XQuery 3.1 says. IIRC, XQuery 1.0 is more prescriptive.