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

Mar*_*nen 5 java xquery saxon exist-db basex

与XSLT和XPath 2.0及更高版本共享的XQuery支持各种数字数据类型,其中两种是xs:doublexs:decimal.如http://www.w3.org/TR/xquery-operators/#casting-to-numerics中所定义,可以转换xs:double为an .xs:decimal

在Java中完成的实现似乎xs:double使用Java double数据类型并xs:decimal使用java.math.BigDecimal类来实现.该类支持两种将a转换double为a的方式BigDecimal,即do BigDecimal.valueOf(doubleValue)new BigDecimal(doubleValue).据/sf/answers/503040891/,前者给出了更直观的结果,而后者给出了更准确的结果,例如BigDecimal.valueOf(1.1)导致1.1new BigDecimal(1.1)导致1.100000000000000088817841970012523233890533447265625.

当我尝试的演员xs:doublexs:decimal与撒克逊和存在,那么

xquery version "1.0";

let $d1 as xs:double := 1.1E0
return xs:decimal($d1)
Run Code Online (Sandbox Code Playgroud)

输出1.100000000000000088817841970012523233890533447265625,同时用BaseX它输出1.1.我认为差异来自不同的实现,BaseX做BigDecimal.valueOf(1.1),Saxon和Exist new BigDecimal(1.1).

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

Mic*_*Kay 4

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

撒克逊语的实际代码是

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