gpt4 book ai didi

java - XSLT 与 javax.xml.transform 的乘法结果不正确 (0.2*0.8*0.8)

转载 作者:行者123 更新时间:2023-12-02 03:22:58 29 4
gpt4 key购买 nike

我有一个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 或 W3CSschool 中的以下示例文件测试此 XSLT 时 here ,我得到的结果是 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() 函数,该函数将源文档中的值(例如 0.8)转换为 float ,无论是在 XSLT 1.0 还是 XSLT 2.0 中。 XSLT 2.0 提供了一种解决方案,您可以通过调用 xs:decimal() 来替换对 number() 的调用,这将为您提供十进制算术而不是二进制 float -点,从而避免舍入误差。但在这两种情况下,您当前正在执行的代码都在执行浮点运算。

根据 W3C 规范 1.0 和 2.0 的规则,该表达式的正确答案实际上是 0.12800000000000003。规范对此没有给予任何宽大处理。但实现者采取了捷径,并使用浮点算术库(更具体地说,用于数字到字符串的转换),而这些库并不是为遵循 W3C 规则而编写的。我强烈怀疑为此查询输出 0.128 的实现正在使用数字到字符串的转换例程,该例程试图比 W3C 规范允许的更智能。

如果想避免这种舍入误差,正确的做法是:

(a) 对于 XSLT 1.0,使用 format-number() 将输出格式化为可能准确(或实际需要)的小数位数

(b) 对于 XSLT 2.0,使用 xs:decimal 算术 - 当您从源文档读取数字时,这意味着显式地将它们设为 xs:decimal,方法是根据将类型声明为 xs 的模式验证源文档:十进制,或使用样式表中的 xs:decimal() 函数。

关于java - XSLT 与 javax.xml.transform 的乘法结果不正确 (0.2*0.8*0.8),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39374850/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com