web-dev-qa-db-ja.com

XSL-丸め/形式番号の問題

私は私のxmlから2 dec位までの数値の値を取得しようとしています。

XML:_<Quantity>0.0050</Quantity>_

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

ただし、XSLにはこの値に問題があるようで、ページの1つの領域に_0.00_を出力し、他の領域に_0.01_を出力します。もちろん、この状況では、すべての領域で_0.01_出力を使用することが望ましいです。

別の領域の値は_4.221_ですが、XSLは_4.23_を出力しています。

メソッドとしての_format-number_は数値を文字列に変換することを理解しています。

これを修正する方法がわからない。


編集:

ちょっといじってから、これがうまくいくことがわかりました:

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

これを介して ウェブサイト

この男が言及しているように、XSLは「バンカーの丸め」を使用して、大きな数字ではなく偶数に丸めます。

解決策はほとんどエレガントではないようで、既にかさばって複雑なXSLファイルに大量の追加機能を追加することを意味します。きっと私は何かが欠けていますか?

26
Julio

なぜフォーマットが非常に矛盾するのかはわかりませんが、メモリからの仕様は...複雑です。

その間、round関数を使用できます( ref )。これは完璧ではありませんが、機能的です。特定の数のsigイチジクが必要な場合は、THE POWER OF MATHS!を使用して、次のような操作を実行できます。

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

20
annakata

XSLT/XPath 1.0の小数には無限の問題がありました。多くの場合、小数を浮動小数点数として表し、半偶数の丸め(バンカーの丸め)を使用する組み合わせです。残念ながら、round(yournum*100) div 100アプローチは、浮動小数点の不正確さのために、私にとってはうまくいきませんでした。たとえば、1.255に100を掛けると、125.49999999999999になります(IEEE 754と想定されているため、これは実装に依存するものではありませんが、すべての実装がそれに従うかどうかはわかりません)。丸められると、これは望ましい126ではなく125になります。

私は次のアプローチを取りましたが、うまくいくと思います(ただし、これは常にトリッキーなエリアなので、あまり自信を宣言しません!)。ただし、EXSLT拡張をサポートするXSLTエンジンに依存します。小数点以下2桁に丸めることを前提としています。

<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>

次のように呼び出すことができます:

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

名前空間は次のとおりです。

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

関数appends a '1'であり、0.001などは加算されないことに注意することが重要です。

XSLT 2.0がオプションである場合(適切な10進数型があるため)、XSLT 2.0を使用する方が間違いなく優れていますが、(痛みを伴う経験から!)オプションではないことがよくあります。

15
Giles

また、round($ number * 100)div 100を実行すると、.4999999の浮動小数点表現が得られ、丸めが正しく機能しないという問題も発生しました。

これを回避するために、これはうまくいくようです:round($ number * 1000 div 10)div 100

0
Sean

私が見つけた上記のすべての答えと比較して

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

便利です。小数点の値を切り捨てません。正確に指定された数値を切り捨てます。数値が指数形式の場合、次のように使用できます。

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

ありがとう

0
Rakesh