Incorrect multiplication result by XSLT with javax.xml.transform (0.2*0.8*0.8)(XSLT与javax.xml.Transform的乘法结果不正确(0.2*0.8*0.8))
问题描述
我有一个XSLT,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="Test">
<Result>
<xsl:value-of select="number(depth)*number(width)*number(height)"/>
</Result>
</xsl:template>
当我用Altova XML或W3CSchoolhere对下面的示例文件测试这个XSLT时,我得到的结果是0.128
示例文件:
<?xml version="1.0" encoding="UTF-8"?>
<Test>
<depth>.8</depth>
<width>.8</width>
<height>.2</height>
</Test>
但是,当我使用Java调用XSLT时,情况发生了变化。我得到的结果是
<Result>0.12800000000000003</Result>
下面是我使用的简单代码:
import javax.xml.transform.*;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
public class TestMain {
public static void main(String[] args) throws IOException, URISyntaxException, TransformerException {
TransformerFactory factory = TransformerFactory.newInstance();
Source xslt = new StreamSource(new File("transform.xslt"));
Transformer transformer = factory.newTransformer(xslt);
Source text = new StreamSource(new File("input.xml"));
transformer.transform(text, new StreamResult(new File("output.xml")));
}
}
问题:为什么Java代码将输出设置为0.12800000000000003? 即使0.12800000000000000也可以理解,但0.12800000000000003是错误的计算。
推荐答案
首先,浮点运算通常会产生这样的舍入误差,因为像0.8这样的数字在xs:Double的值空间中无法准确表示。
其次,您的样式表显式使用了number()
函数,该函数在XSLT 1.0和XSLT 2.0中都将源文档中的值(如0.8)转换为浮点数。XSLT 2.0提供了一种解决方案,因为您可以将对number()
的调用替换为对xs:decimal()
的调用,这将为您提供十进制算术而不是二进制浮点数,从而避免舍入误差。但您当前执行的代码在这两种情况下都执行浮点运算。
根据W3C规范在1.0和2.0中的规则,这个表达式的正确答案实际上是0.12800000000000003。该规范没有对此给予任何宽大处理。但是实现者走捷径,将库用于浮点算术(更具体地说,用于数字到字符串的转换),而这些库并不是按照W3C规则编写的。我强烈怀疑为该查询输出0.128的实现正在使用一个数字到字符串的转换例程,该例程试图比W3C规范所允许的更智能。
如果您想避免这种舍入误差,正确的方法是:
(A)在XSLT 1.0中,使用Format-Numbers()将输出格式化为可能准确(或实际需要)的小数位数
(B)在XSLT 2.0中,使用xs:decimal算法-当您从源文档读取数字时,这意味着显式地使它们成为xs:decimal,方法是根据将类型声明为xs:decimal的架构验证源文档,或者使用样式表中的xs:decimal()函数。
这篇关于XSLT与javax.xml.Transform的乘法结果不正确(0.2*0.8*0.8)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:XSLT与javax.xml.Transform的乘法结果不正确(0.2*0.8*0.8)
基础教程推荐
- 如何使用 Eclipse 检查调试符号状态? 2022-01-01
- 如何在不安装整个 WTP 包的情况下将 Tomcat 8 添加到 Eclipse Kepler 2022-01-01
- 如何使用 Stream 在集合中拆分奇数和偶数以及两者的总和 2022-01-01
- 如何强制对超级方法进行多态调用? 2022-01-01
- 如何对 HashSet 进行排序? 2022-01-01
- 首次使用 Hadoop,MapReduce Job 不运行 Reduce Phase 2022-01-01
- 由于对所需库 rt.jar 的限制,对类的访问限制? 2022-01-01
- Java 中保存最后 N 个元素的大小受限队列 2022-01-01
- Spring Boot Freemarker从2.2.0升级失败 2022-01-01
- 在螺旋中写一个字符串 2022-01-01