This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 1406 - Serialization of float and double via decimal problematic
Summary: Serialization of float and double via decimal problematic
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: Functions and Operators 1.0 (show other bugs)
Version: Last Call drafts
Hardware: PC Windows 2000
: P2 normal
Target Milestone: ---
Assignee: Ashok Malhotra
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-05-13 17:23 UTC by Mary Holstege
Modified: 2005-09-29 11:03 UTC (History)
0 users

See Also:


Attachments

Description Mary Holstege 2005-05-13 17:23:21 UTC
Serialization for floats and double in the range .000001 <= x < 1000000
is defined by first casting the value to decimal and then following the
serialization rules for decimal. [Ref: FO 17.1.2 Casting to xs:string and
xdt:untypedAtomic] 

The problem with this is that decimal is only guaranteed to support 18 digits,
so serialization of some float and double values can result in numbers that
cannot be supported by most implementations, resulting in the error
"err:FOCA0001, input value too large for decimal".
[Ref: FO 17.1.3.3 Casting to xs:decimal]

It seems like a serious misfeature to cause a query to fail in serializing a
value which one has carefully chosen to have a sufficient number of bits.
Worse, since validation may be defined in terms of serialization
[Ref QLang 3.13 Validate Expressions and DM 4 Infoset Mapping], validation can
cause a query to fail on data that would actually validate.

Possible solutions:
(a) Forget the pretty printing. If you want pretty numbers, provide
    a number formatting function, or use strings.  If it is necessary
    for XPath compatibility, only do it in XPath 1.0 compatibility mode.
    Thus the serialization of a float or double value would always be
    in scientific notation.
(b) Disallow serialization as the basis for validation. This does not solve
    the general problem with serializations of float and double values, but 
    at least guarantees that an instance valid against a schema can be validated 
    against that same schema successfully, which strikes us a fairly
    fundamental invariant.
(c) Define a value-preserving non-cosmetic variant of serialization and specify
    that serialization of a data model for the purposes of constructing an
    infoset for validation must use this value-preserving variant.
(d) Require more than 18 digits of support for decimal, so that coercion to
    decimal from double is guaranteed not lose information.

(On behalf of Schema WG)
Comment 1 Michael Kay 2005-05-13 18:00:26 UTC
I've never really understood how an implementation can get away with only
supporting 18 digits of precision, since xs:unsignedLong requires 20; but that's
incidental.

For format-number() in XSLT 2.0 we specify that the behaviour is as if the
xs:double is converted to an xs:decimal using an implementation of xs:decimal
that supports infinite precision, and we then describe how this notional
xs:decimal is converted to a string. This does not require that the
implementation actually supports such an xs:decimal type, only that
double->string conversion behaves as if it did. I would suggest that we adopt
the same approach here.

Outputting natural numbers such as 1, 2, and 3 in exponential notation is not an
option. Doubles arise all the time as a result of our implicit rules for
handling untyped data; we can't possibly contemplate the output of 

See Chapter <xsl:value-of select="@chap + 1"/>

being "See Chapter 2e0".

Michael Kay
Comment 2 Ashok Malhotra 2005-07-22 12:39:51 UTC
The joint WGs agreed to close this bug by adding the words "as though using an
implementation of xs:decimal that imposes no limits on the totalDigits or
fractionDigits facets" to the description in 17.1.2 of casting flost/double
values between one million and one millionth to xs:string.