xml XSL - 舍入/格式数字问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3805248/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 13:18:44  来源:igfitidea点击:

XSL - rounding/format-number problem

xmlxsltformattingnumbersrounding

提问by Julio

I'm trying to get the value of a number to 2 dec places from my xml.

我试图从我的 xml 中获取一个数字的值到 2 个十进制位置。

XML:<Quantity>0.0050</Quantity>

XML:<Quantity>0.0050</Quantity>

XSL:<xsl:value-of select="format-number($quantity, '####0.00')" />

XSL:<xsl:value-of select="format-number($quantity, '####0.00')" />

However XSL seems to have a problem with this value and outputs 0.00in one area of the page and 0.01in the other. Of course in this situation it is favourable to have 0.01output in all areas.

但是 XSL 似乎对此值有问题,并0.00在页面的一个区域和另一个区域中输出0.01。当然,在这种情况下,0.01在所有领域都有产出是有利的。

Another area has the value 4.221yet the XSL is outputting 4.23.

另一个区域具有值,4.221但 XSL 正在输出4.23.

I do realise that format-numberas a method converts a number to a string.

我确实意识到format-number作为一种方法将数字转换为字符串。

Not sure how to fix this.

不知道如何解决这个问题。



EDIT:

编辑:

Ok after a bit of mucking around i found that this works:

好的,经过一番折腾,我发现这有效:

<xsl:value-of select='format-number( round(100*$quantity) div 100 ,"##0.00" )' />

Via this website

通过本网站

As this guy mentions XSL uses 'bankers rounding' to round to even numbers instead of the bigger ones.

正如这个人提到的,XSL 使用“银行家舍入”来舍入为偶数而不是更大的数字。

The solution hardly seems elegant, and means adding a ton of extra functions to an already bulky and complicated XSL file. Surely i'm missing something?

该解决方案似乎并不优雅,并且意味着向已经庞大而复杂的 XSL 文件添加大量额外功能。我肯定错过了什么?

采纳答案by annakata

Not sure why format would be so inconsistent but from memory the spec for it is...complex.

不知道为什么格式会如此不一致,但从记忆中它的规范是......复杂。

Meantime, you can use the roundfunction (ref). Which is less than perfect, but is functional. If you need to have a particular number of sig figs you can use THE POWER OF MATHS!and do something like:

同时,您可以使用round函数 ( ref)。这并不完美,但功能齐全。如果您需要特定数量的无花果,您可以使用数学的力量!并执行以下操作:

<xsl:value-of select="round(yournum*100) div 100"/>

<xsl:value-of select="round(yournum*100) div 100"/>

回答by Giles

I've had endless trouble with decimals in XSLT/XPath 1.0, often a combination of it representing decimals as floating-point numbers and it using half-even rounding (banker's rounding). Unfortunately, the round(yournum*100) div 100approach didn't work for me, due to floating-point imprecision. For example, multiplying 1.255 by 100 gives 125.49999999999999 (this isn't meant to be implementation dependent, as it's supposed to be IEEE 754, but I don't know if all implementations do adhere to that). When rounded, this then gives 125, rather than the desired 126.

我在 XSLT/XPath 1.0 中遇到了小数问题,通常是将小数表示为浮点数并使用半偶数舍入(银行家的舍入)的组合。不幸的是,round(yournum*100) div 100由于浮点不精确,这种方法对我不起作用。例如,将 1.255 乘以 100 得到 125.49999999999999(这并不意味着依赖于实现,因为它应该是 IEEE 754,但我不知道是否所有实现都遵守这一点)。舍入后,这将给出 125,而不是所需的 126。

I've taken the following approach, which I think works (although this is always a tricky area so I won't declare too much confidence!). However, it depends on your XSLT engine supporting EXSLT extensions. It presumes you want to round to two decimal places.

我采用了以下方法,我认为它有效(尽管这总是一个棘手的领域,所以我不会宣布太多的信心!)。但是,这取决于您的 XSLT 引擎是否支持 EXSLT 扩展。它假定您要四舍五入到两位小数。

<func:function name="local:RoundHalfUp">
    <xsl:param name="number"/>

    <xsl:choose>
        <xsl:when test="contains($number, '.')">
            <xsl:variable name="decimal" select="estr:split($number, '.')[2]"/>
            <xsl:choose>
                <xsl:when test="string-length($decimal) &gt; 2">
                    <func:result select="format-number(concat($number, '1'), '0.00')"/>
                </xsl:when>
                <xsl:otherwise>
                    <func:result select="format-number($number, '0.00')"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:when>
        <xsl:otherwise>
            <func:result select="format-number($number, '0.00')"/>
        </xsl:otherwise>
    </xsl:choose>

</func:function>

which can be called like:

可以这样调用:

<xsl:value-of select="local:RoundHalfUp(1.255)"/>

The namespaces are:

命名空间是:

xmlns:func="http://exslt.org/functions"
xmlns:estr="http://exslt.org/strings"
xmlns:local="http://www.acme.org/local_function"

It's important to note that the function appendsa '1', not adds 0.001 or similar.

请务必注意,该函数会附加一个“1”,而不是添加 0.001 或类似值。

Definately better to use XSLT 2.0 if it's an option (because it has a proper decimal type), but I know that's often not an option (from painful experience!).

如果它是一个选项(因为它具有适当的十进制类型),那么使用 XSLT 2.0 肯定会更好,但我知道这通常不是一个选项(从痛苦的经验中!)。

回答by Rakesh

Compared to all above answers i found

与我发现的所有上述答案相比

<xsl:value-of select="format-number(xs:decimal($quantity), '####0.00')" />

is useful, it is not truncating any decimal point values. truncating exactly specified numbers. if number is in Exponential format we can use as follows:

很有用,它不会截断任何小数点值。截断精确指定的数字。如果数字是指数格式,我们可以使用如下:

<xsl:value-of select="format-number(xs:decimal(number($quantity)), '####0.00')" />

Thanks

谢谢

回答by Sean

I've also encountered the issue whereby if you did round($number * 100) div 100 you get a floating point representation of .4999999 and the rounding doesn't work properly.

我也遇到过这样的问题,如果你做 round($number * 100) div 100 你得到 0.4999999 的浮点表示并且舍入不能正常工作。

To get around this, This seems to work: round($number * 1000 div 10) div 100

为了解决这个问题,这似乎有效:round($number * 1000 div 10) div 100