与 XSLT 和 XPath 2.0 及更高版本共享的 XQuery 支持各种数字数据类型,其中两种是 xs:double
和 xs:decimal
。可以将 xs:double
转换为 xs:decimal
,如 http://www.w3.org/TR/xquery-operators/#casting-to-numerics 中所定义.
在 Java 中完成的实现似乎使用 Java double
数据类型实现 xs:double
,使用 java 实现
类。该类支持将 xs:decimal
.math.BigDecimaldouble
转换为 BigDecimal
的两种方法,即执行 BigDecimal.valueOf(doubleValue)
和 new BigDecimal(doubleValue )
。根据https://stackoverflow.com/a/7186298/252228 , 前者给出更直观的结果而后者给出更正确的结果,例如 BigDecimal.valueOf(1.1)
结果为 1.1
而 new BigDecimal( 1.1)
结果为 1.100000000000000088817841970012523233890533447265625
。
当我尝试使用 Saxon 和 Exist 将 xs:double
转换为 xs:decimal
时
xquery version "1.0";
let $d1 as xs:double := 1.1E0
return xs:decimal($d1)
输出 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 实现转换操作的正确方法?
最佳答案
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 位必须基本如图所示。
Saxon 中的实际代码是
public DecimalValue(double in) throws ValidationException {
try {
BigDecimal d = new BigDecimal(in);
value = d.stripTrailingZeros();
} catch (NumberFormatException err) {
//...
}
关于java - 应该转换 xs :double to xs:decimal be implemented as BigDecimal. valueOf(double) 还是 new BigDecimal(double)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28264587/