Search code examples
stringtype-conversionnumbersxquery

Type casting issue in Xquery


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.


Solution

  • 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.