2015-10-23 96 views
0

我們正面臨使用XSLT舍入和格式數函數的一個非常奇怪的問題。可以說我有一個像131.855這樣的數字,我想把它舍入到小數點後兩位。我預計131.86作爲答案,但XSLT round()函數將其折算爲131.85。我嘗試使用「圓(131.855 * 100)div 100」,但它不起作用。而如果我必須四捨五入127.855這樣的數字,它會使用相同的代碼正確地舍入到127.86,即「round(127.855 * 100)div 100」。另外,奇怪的是,如果我嘗試將131.755四捨五入到131.76!很奇怪。 我們也嘗試過使用format-number()函數,但這也給出了奇怪的結果。例如,如果我採用編號349615.225,並且我使用格式編號(即格式編號(349615.225,'#。##')),它會給出349615.22,而我希望小數爲.23。但是,如果使用的131.855號格式它得到的轉換爲131.86 ...XSLT舍入問題

我也使用round()函數裏面號格式(嘗試),但它也給了相似的結果..

我們正在使用XSLT 1.0。更改爲XSLT 2.0似乎是一項艱鉅的任務。我看到的唯一解決方法是使用一些java函數,並從XSL中調用它來舍入。

任何想法將不勝感激。

編輯:

奇怪的是完全一樣的問題恰好與Java的Math.round功能。

+0

您正在使用哪種XSLT處理器? –

+0

這似乎是由浮點運算引起的錯誤。我已經設法重現了Xalan http://xsltransform.net/bFN1y8S和Saxon http://xsltransform.net/bFN1y8S/1中的問題 - 但是好奇地不在libxslt中,所以這可能是一個Java引擎問題。 –

+0

「* Java的Math.round函數發生同樣的問題*」那麼你去吧。 –

回答

1

您可以使用以下方法:

format-number(round(100 * $number) div 100, '#.00')

round()功能四捨五入到最接近的整數數字,只是使用的round()可能無法正常輪數。
format-number()通過修剪數據來格式化數據(我猜),這會導致數據丟失。
使用round()format-number()都應該有效地工作。

下面的例子描述了不同的行爲。

輸入:

<root>5.225</root> 

XSLT:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="text" /> 
    <xsl:template match="/"> 
     <xsl:value-of select="round(*)"/> 
     <xsl:text>&#xa;</xsl:text> 
     <xsl:value-of select="round(100 * *)"/> 
     <xsl:text>&#xa;</xsl:text> 
     <xsl:value-of select="format-number(*, '#.00')"/> 
     <xsl:text>&#xa;</xsl:text> 
     <xsl:value-of select="format-number(round(100 * *) div 100, '#.00')"/> 
    </xsl:template> 
</xsl:transform> 

輸出:
5.22
5.23

+0

「* round()函數將該數字四捨五入到最接近的偶數,*」不,它將四捨五入到最接近的整數,並且它總是向上** ** **。 - 「* format-number()通過修剪數據來格式化數字,*」函數的行爲在spec中沒有很好的定義,你會發現不同的處理器實現它的方式不同(儘管我不知道一個截斷)。 –

+0

是的,當我說'even'時,我會小心點:)讓我更新我的答案..'format-number()',是我對它的行爲方式的假設..謝謝@ michael.hor257k! –

+0

我們在131.855上也試過這個選項,但它不工作。爲了測試我在Eclipse中使用默認的XSLT處理器 –

0

首先要明白的是,當你寫一個號碼 如131.855,它所代表的實際值並不完全在131.85和131.86之間。沒有雙精度浮點數在數值上等於131.855,因此您操作的實際值略低於或稍高。這種不精確性一旦你寫下數字就會出現,它不僅會在你對數字進行算術運算時出現。當你乘以100時,這種差異就會變大,而當你使用round()時,它將會變成最接近的整數,這取決於近似值是在起始還是下降。因此,鑑於XSLT 1.0僅提供浮點數字,因此無法避免此類問題。

在XSLT 2中。0你可以使用十進制數字,其行爲更像人類往往期望的方式。

+0

那麼爲什麼127.855會輪到127.86和131.755輪到131.76? –

+0

這是不可預知的,你得到的數字是高於還是低於你寫的數字。在我的系統上,當我寫127.855時,我得到的數字是127.8550000000000039790393202565610408782958984375,而當我寫131.755時,我得到的數字是131.7549999999999954525264911353588104248046875 –