是应该将xs:double转换为xs:decimal实现为BigDecimal.valueOf(double)还是new BigDecimal(double)?

时间:2015-02-01 15:51:08

标签: java xquery saxon exist-db basex

与XSLT和XPath 2.0及更高版本共享的XQuery支持各种数字数据类型,其中两种是xs:doublexs:decimal。根据{{​​3}}中的定义,可以将xs:double转换为xs:decimal

在Java中完成的实现似乎使用Java xs:double数据类型实现double,使用xs:decimal类实现java.math.BigDecimal。该类支持两种将double转换为BigDecimal的方式,即执行BigDecimal.valueOf(doubleValue)new BigDecimal(doubleValue)。根据{{​​3}},前者提供更直观的结果,而后者提供更正确的结果,例如BigDecimal.valueOf(1.1)导致1.1new BigDecimal(1.1)导致{{1} }}

当我尝试使用Saxon和Exist 1.100000000000000088817841970012523233890533447265625演员xs:double

xs:decimal

输出xquery version "1.0"; let $d1 as xs:double := 1.1E0 return xs:decimal($d1) ,而使用BaseX输出1.100000000000000088817841970012523233890533447265625。我想差异来自不同的实现,BaseX执行1.1,Saxon和Exist执行BigDecimal.valueOf(1.1)

我的问题是:哪种方法是根据http://www.w3.org/TR/xquery-operators/#casting-to-numerics实施强制转换操作的正确方法?

2 个答案:

答案 0 :(得分:4)

需要xs:decimal的实现来支持至少18个有效十进制数字,如果它这样做,最接近xs:decimal的xs:double值1.1将是1.100 000 000 000 088而不是1.1。 (这实际上是19位而不是18位,但即使是18位,也应该显示与1.1的差异。)所以我认为返回小数1.1是不符合的。数字的位数是超过18位的实现定义,但前18位必须基本上如图所示。

Saxon的实际代码是

public DecimalValue(double in) throws ValidationException {
        try {
            BigDecimal d = new BigDecimal(in);
            value = d.stripTrailingZeros();
        } catch (NumberFormatException err) {
            //...
        }

答案 1 :(得分:3)

XQuery建议书将实现了双值的最接近的十进制表示形式。原因是规范应该支持任意编程语言的实现。

但是,由于您提示BigDecimal.valueOf(d)new BigDecimal(d)不相同,下一版本的BaseX(版本8.0)将返回更准确的结果。