为什么在Jean和Sesame/OpenRDF的SPARQL处理器之间对除法运算的解释发生了变化



以下SPARQL查询在两个流行SDK(Jena和Sesame/OpenRDF)的SPARQL引擎上运行时会产生不同的结果:

PREFIX xsd:<http://www.w3.org/2001/XMLSchema#>
SELECT  ?v1 ?v2 ?v3 ?v4 ?v5 ?v6
WHERE
{
    BIND (            1    / 3             as ?v1)
    BIND (  xsd:float(1    / 3)            as ?v2)
    BIND (  xsd:float(1)   / 3             as ?v3)
    BIND ( (          1.0  / 3)            as ?v4)
    BIND (  xsd:float(1.0  / 3)            as ?v5)
    BIND (  xsd:float(1.0) / 3             as ?v6)
}

Jena最新版本的结果对我来说很有意义(为了可读性而格式化):

v1: 0.333333333333333333333333
v2: "0.333333333333333333333333"^^xsd:float
v3: "0.33333334"^^xsd:float
v4: 0.333333333333333333333333
v5: "0.333333333333333333333333"^^xsd:float
v6: "0.33333334"^^xsd:float

另一方面,Sesame/OpenRDF的最新版本返回(为了可读性而格式化):

v1: "0"^^<http://www.w3.org/2001/XMLSchema#decimal>
v2: "0.0"^^<http://www.w3.org/2001/XMLSchema#float>
v3: "0.33333334"^^<http://www.w3.org/2001/XMLSchema#float>
v4: "0.3"^^<http://www.w3.org/2001/XMLSchema#decimal>
v5: "0.3"^^<http://www.w3.org/2001/XMLSchema#float>
v6: "0.33333334"^^<http://www.w3.org/2001/XMLSchema#float>

强调一下:Jena从来不会像Sesame/OpenRDF那样返回0、0.0或0.3。有人能解释一下为什么数字结果会有这样的差异吗?如何对同一个SPARQL查询获得相同的结果?或者,哪一个是正确的(从某种意义上说,无论数学正确性如何,都能正确地实现SPARQL标准)?

Sesame实现除法运算符时采用了不同的舍入/缩放策略来解释这种差异。

第一个操作员:

1 / 3 as ?v

将两个整数值除法并将结果绑定到?v、 其将是十进制类型的值。

由于1/3是一个具有非终止小数展开的分数,我们需要对结果进行四舍五入。然而,由于两个输入变量的小数位数(即小数位数)为零,Sesame的MathUtil也将结果的小数位数设置为零,因此除法结果(0.3333…)被缩放为零位数并取整,结果为0。

您可以在Sesame中通过显式地将比例添加到您的输入值来绕过这一点。例如:

SELECT  ?v1 
WHERE
{
    BIND ( 1.0000 / 3 as ?v1)
}

将导致:

?v1:  "0.3333"^^<http://www.w3.org/2001/XMLSchema#decimal>    

请注意,我们在这里实际做的是将一个输入值从整数更改为十进制。这在某种程度上类似于在Java中执行1/3会导致0,但您可以通过将类型转换为double来绕过这一点。

据我所知,从XPath规范(定义了SPARQL重用的除法运算符)来看,Jena和Sesame的行为都符合规范,因为数字运算的比例数字的选择是由实现定义的。

当然,这并不是说,如果Sesame在除法时真的在这样的重复分数上使用了更高的精度,那就不会更实用了。作为改进请求登录在http://www.openrdf.org/issues/browse/SES-1063,并且由于这是一件微不足道的事情,因此这将在下一个版本中得到支持。同时,我希望以上内容能给你一个合适的解决方法。

最新更新