本文介紹了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)的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,