因子XSLT限制?

时间:2009-07-22 19:20:12

标签: xml internet-explorer firefox xslt

我在XSLT中实现了以下factorial函数:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="/">
        <xsl:apply-templates>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="factorial" name="factorial">
        <xsl:param name="n" select="@n" />
        <xsl:param name="f" select="1" />
        <xsl:if test="$n &gt; 1">
            <xsl:call-template name="factorial">
                <xsl:with-param name="n">
                    <xsl:value-of select="$n - 1" />
                </xsl:with-param>
                <xsl:with-param name="f">
                    <xsl:value-of select="$f * $n" />
                </xsl:with-param>
            </xsl:call-template>
        </xsl:if>
        <xsl:if test="$n = 1">
            <xsl:value-of select="$f" />
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

在Firefox和IE7中,170!工作正常但171!仅返回NaN。这是XSLT / XPath数学中明确定义的限制,还是有一种方法可以获得更高的n!值?

3 个答案:

答案 0 :(得分:3)

为XPath 1.0添加正确答案,在XPath 2.0中有xs:integer数据类型, xs:integer 的绝对值没有最大值。

Saxon实现了BigInteger算法,并给出了代码(通过添加xs:integer类型略有改变):

    

<xsl:template match="factorial" name="factorial">
    <xsl:param name="n" as="xs:integer"
     select="xs:integer(@n)" />
    <xsl:param name="f" as="xs:integer" select="1" />

    <xsl:if test="$n gt 1">
        <xsl:call-template name="factorial">
            <xsl:with-param name="n">
                <xsl:value-of select="$n - 1" />
            </xsl:with-param>
            <xsl:with-param name="f">
                <xsl:value-of select="$f * $n" />
            </xsl:with-param>
        </xsl:call-template>
    </xsl:if>
    <xsl:if test="$n = 1">
        <xsl:value-of select="$f" />
    </xsl:if>
</xsl:template>

当它应用于以下XML文档时:

<factorial n = "171"/>

产生了正确的结果:

1241018070217667823424840524103103992616605577501693185388951803611996075221691752992751978120487585576464959501670387052809889858690710767331242032218484364310473577889968548278290754541561964852153468318044293239598173696899657235903947616152278558180061176365108428800000000000000000000000000000000000000000

当然,我更喜欢在单个表达式中使用FXSL library来写这个:

<强> f:foldl(f:mult(), 1, 1 to 171)

在这个XSLT样式表中:

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
>
   <xsl:import href="../f/func-dvc-foldl.xsl"/>
   <xsl:import href="../f/func-Operators.xsl"/>

    <xsl:output  encoding="UTF-8" method="text"/>

    <xsl:template match="/">
      <xsl:value-of select="f:foldl(f:mult(), 1, 1 to 171)"/>
    </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:2)

XPath规范defines number输入如下:

  

数字表示浮点数。数字可以具有任何双精度64位格式IEEE 754值。

所以限制是明确的。我没有检查过,但鉴于171大!是的,你可能正在打它们。

答案 2 :(得分:0)

我猜测你的问题是依赖于XSLT实现的。

这看起来像标准的溢出问题。我通过使用此处的JavaScript因子实现复制问题找到了一个提示:http://www.cs.uml.edu/~ytran/factorial.html

在另一种语言中,我会使用BigInteger库来获得如此大的数字。使用Google快速搜索[terms:XSLT BigInteger]会发现XSLT没有原生的BigInteger类型。