Java xs:double到xs:decimal的转换应该实现为BigDecimal.valueOf(double)还是新的BigDecimal(double)?
XQuery与XSLT和XPath2.0及更高版本共享,支持各种数字数据类型,其中两种是Java xs:double到xs:decimal的转换应该实现为BigDecimal.valueOf(double)还是新的BigDecimal(double)?,java,xquery,saxon,exist-db,basex,Java,Xquery,Saxon,Exist Db,Basex,XQuery与XSLT和XPath2.0及更高版本共享,支持各种数字数据类型,其中两种是xs:double和xs:decimal。可以将xs:double强制转换为xs:decimal,如中所定义 在Java中完成的实现似乎使用Javadouble数据类型实现xs:double,并使用Java.math.BigDecimal类实现xs:decimal。该类支持将double转换为BigDecimal的两种方法,即执行BigDecimal.valueOf(doubleValue)和新建BigDec
xs:double
和xs:decimal
。可以将xs:double
强制转换为xs:decimal
,如中所定义
在Java中完成的实现似乎使用Javadouble
数据类型实现xs:double
,并使用Java.math.BigDecimal
类实现xs:decimal
。该类支持将double
转换为BigDecimal
的两种方法,即执行BigDecimal.valueOf(doubleValue)
和新建BigDecimal(doubleValue)
。根据,前者给出更直观的结果,而后者给出更正确的结果,例如BigDecimal.valueOf(1.1)
产生1.1
,而新的BigDecimal(1.1)
产生1.1000000000000088817841970012523233890533447265625
当我尝试用Saxon将xs:double
转换为xs:decimal
并存在时
xquery version "1.0";
let $d1 as xs:double := 1.1E0
return xs:decimal($d1)
输出1.1000000000000088817841970012523233890533447265625
,而使用BaseX它输出1.1
。我认为这种差异是由不同的实现造成的,BaseX执行BigDecimal.valueOf(1.1)
,Saxon和Exist执行new BigDecimal(1.1)
我的问题是:根据XQuery的建议,哪种方法是实现cast操作的正确方法取决于双精度值的最接近的十进制表示应该是什么。原因是该规范应该支持任意编程语言的实现
但是,由于您提示
BigDecimal.valueOf(d)
和新的BigDecimal(d)
不是等价的,BaseX的下一个版本(8.0版)将返回更准确的结果。xs:decimal的实现需要支持至少18个有效的十进制数字,如果它支持18个有效的十进制数字,最接近xs:double值1.1的xs:decimal将是1.100000 000088,而不是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) {
//...
}
我想说,无论哪种方法都是正确的,而且所有的实现都正确地实现了规范。它说如果ST是xs:float或xs:double,那么TV是xs:decimal值,在实现能够表示的xs:decimal值集中,在数值上最接近SV,我想说两者都返回处理器能够处理的数值上最接近的值。我不太明白。如果规范中说“至少有18位有效的十进制数字”,为什么返回
1.100000
(可以短接到1.1
,而不丢失有效数字)是不正确的?我不认为会。1.1和1.100 000只是同一个数字的不同表示形式,因此如果您实际上没有返回任何不同的值。我所说的是,双精度1.1e0的数值与十进制1.1不同,如果您将小数保持在18位或以上,则会显示差异。@MichaelKay,将格式化数字(xs:decimal(1.1e0),'0.00000000000000000000000')eq'1.100000000000009'
是一个测试用例,如果XQuery 3.0实现的xs:decimal
至少包含所需的18个有效数字,那么它应该通过该测试吗?@MartinHonnen,是的,我认为这是一个合法的测试,虽然我对将边缘案例放入测试套件的兴趣因为它们往往引起的大量讨论而减弱。。。