我们在使用XSLT舍入和Format-number函数时遇到了一个非常奇怪的问题。假设有一个数字,比如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,并在此使用format-number,即format-number(349615.225,'#.##'),它会给出349615.22,而我期望小数是。23。但是如果我在131.855上使用format-number,它会被转换为131.86…
我也尝试过在format-number()中使用round()函数,但它也给出了类似的结果。
我们正在使用XSLT 1.0。转换到XSLT 2.0似乎是一项艰巨的任务。我看到的唯一解决方法是使用一些java函数并在XSL中调用它来进行舍入。
任何想法都将受到高度赞赏。
编辑:奇怪的是,同样的问题也发生在Java的Math中。圆的函数。
您可以使用以下命令:
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>
</xsl:text>
<xsl:value-of select="round(100 * *)"/>
<xsl:text>
</xsl:text>
<xsl:value-of select="format-number(*, '#.00')"/>
<xsl:text>
</xsl:text>
<xsl:value-of select="format-number(round(100 * *) div 100, '#.00')"/>
</xsl:template>
</xsl:transform>
输出:
5
523年
5.22
5.23
首先要理解的是,当您写一个像131.855这样的数字时,它所代表的实际值并不完全是131.85和131.86之间的中间值。没有双精度浮点数在数值上完全等于131.855,因此您正在操作的实际值略低于或略高于此值。当你把数字写下来的时候,这种不精确性就会出现,而不仅仅是当你对它做算术的时候。当你把它乘以100时,这个差会被放大,当你使用round()时,它会变成最接近的整数,这取决于最初的近似值是上还是下。因此,鉴于XSLT 1.0只提供浮点数,没有办法避免这种问题。
在XSLT 2.0中可以使用十进制数,它的行为更符合人们的期望。