【问题标题】:XSLT - using round() functionXSLT - 使用 round() 函数
【发布时间】:2023-03-21 14:16:02
【问题描述】:

我有这样的xml,

<doc>
    <p>20</p>
    <p>20</p>
    <p>20</p>
    <p>100</p>
    <t>160</t>
</doc>

包含数字的&lt;p&gt;元素有4个,&lt;t&gt;代表以上4个&lt;p&gt;元素的总和。

我的目标是计算这些&lt;p&gt;元素的百分比并显示。

这是我为它编写的 xsl 代码,

    <xsl:variable name="val1" select="abc:get-int-value(doc/p[1]/text())" as="xs:double"/>
    <xsl:variable name="val2" select="abc:get-int-value(doc/p[2]/text())" as="xs:double"/>
    <xsl:variable name="val3" select="abc:get-int-value(doc/p[3]/text())" as="xs:double"/>
    <xsl:variable name="val4" select="abc:get-int-value(doc/p[4]/text())" as="xs:double"/>
    <xsl:variable name="valTotal" select="abc:get-int-value(doc/t/text())" as="xs:double"/>

    <xsl:variable name="precentage1" select="round(($val1 div $valTotal)*100)" as="xs:double"/>
    <xsl:variable name="precentage2" select="round(($val2 div $valTotal)*100)" as="xs:double"/>
    <xsl:variable name="precentage3" select="round(($val3 div $valTotal)*100)" as="xs:double"/>
    <xsl:variable name="precentage4" select="round(($val4 div $valTotal)*100)" as="xs:double"/>

    <xsl:template match="doc">
        <xsl:value-of select="$precentage1"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="$precentage2"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="$precentage3"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="$precentage4"/>
    </xsl:template>

    <xsl:function name="abc:get-int-value" as="xs:double">
        <xsl:param name="text" as="xs:string"/>

        <xsl:analyze-string select='$text' regex='\d+'>
            <xsl:matching-substring>
                <xsl:sequence select="number(.)"/>
            </xsl:matching-substring>
        </xsl:analyze-string>
    </xsl:function>

但是,它给出的百分比值是 13、13、13 和 63。所以这些数字的总和是 102。(字面意思应该是 100、99 或 101)。似乎 p[4] 的百分比值已四舍五入到 63 而不是 62。

为什么会发生这种情况,我该如何解决?

【问题讨论】:

    标签: xml xslt xslt-2.0


    【解决方案1】:

    为什么会这样

    您的预期值是错误的,甚至没有意义。 20 div 160 是 12.5,100 div 160 是 62.5。 12.5 向上取整到 13,62.5 向上取整到 63,这些就是您看到的值。

    四舍五入本质上会产生不精确的值,因此您不能指望四个四舍五入的百分比总和为 100。

    我该如何解决这个问题

    我认为您需要决定如何解决这种差异。 round() 函数完全按照它应该的方式工作。

    【讨论】:

      【解决方案2】:

      我该如何解决这个问题?

      正如其他人已经解释的那样,您无法“修复”此问题。

      不过,您可以通过使用round-half-to-even() 而不是round() 稍微缓解这个问题。碰巧的是,在给定的示例中,它只会将问题转移到另一端 - 即结果将是 12、12、12、62,总共 98。但平均而言,舍入误差会更小。

      【讨论】:

        【解决方案3】:

        有关将一组百分比四舍五入的算法的一些讨论,以使总数加起来为 100(但不是专门在 XSLT 上下文中),请参阅

        How to make rounded percentages add up to 100%

        【讨论】:

          【解决方案4】:

          round 函数就是这样工作的:它返回一个与参数值最接近的整数,这意味着 round(62.5) = 63

          你可以做的是从 100 中提取 percenatge1、percentage2 和 percent3 并得到 percent4,因为所有这三个百分比值应该给你总共 100%,即:

          <xsl:variable name="precentage4" select="100 - $precentage1 - $precentage2 - $precentage3" as="xs:double"/>
          

          【讨论】:

          • 感谢您的回答。确切的百分比值是 12.51、12,51、12.51 和 62.25.. 所以 62.25 应该四舍五入到 62?
          • @sanjay,怎么会? 100 恰好是 62.5%160
          • @sanjay 你从哪里得到这些百分比值?正确的值为 12.5、12.5、12.5 和 62.5。
          • @sanjay 舍入 向下 到 62。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多