与XSLT和XPath 2.0及更高版本共享的XQuery支持各种数字数据类型,其中两种是xs:double
和xs: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.1
而new 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实施强制转换操作的正确方法?
答案 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)将返回更准确的结果。