XSL-arrondissement / format-Nombre problème
je vais essayer d'obtenir la valeur d'un nombre à 2 déc lieux de mon xml.
XML:<Quantity>0.0050</Quantity>
XSL:<xsl:value-of select="format-number($quantity, '####0.00')" />
Toutefois XSL semble avoir un problème avec cette valeur et sorties 0.00
dans une zone de la page et 0.01
dans l'autre. Bien sûr, dans cette situation, il est favorable d'avoir 0.01
sortie dans toutes les zones.
une autre zone a la valeur 4.221
pourtant la XSL est en train de sortir 4.23
.
je dois réaliser que format-number
comme méthode convertit un nombre en chaîne.
Je ne sais pas comment réparer ça.
EDIT:
Ok après un peu de nettoyage, j'ai trouvé que cela fonctionne:
<xsl:value-of select='format-number( round(100*$quantity) div 100 ,"##0.00" )' />
Par site web
comme ce type mentionne XSL utilise 'bankers rounding' pour arrondir à des nombres pairs au lieu des plus grands.
la solution ne semble guère élégante, et signifie ajouter une tonne de fonctions supplémentaires pour un fichier XSL déjà volumineux et compliqué. Certes, je suis en manque de quelque chose?
4 réponses
Je ne sais pas pourquoi le format serait si incohérent mais de mémoire la spécification pour cela est...complexe.
en attendant, vous pouvez utiliser le round
fonction ( ref). Ce qui est moins que parfaite, mais elle est fonctionnelle. Si vous avez besoin d'un certain nombre de sig figues, vous pouvez utiliser LE POUVOIR DES MATHÉMATIQUES! et faire quelque chose comme:
<xsl:value-of select="round(yournum*100) div 100"/>
j'ai eu des problèmes sans fin avec les décimales dans XSLT/XPath 1.0, souvent une combinaison de celui-ci représentant des décimales comme des nombres à virgule flottante et il en utilisant l'arrondi à moitié égal (arrondi banquier). Malheureusement, le round(yournum*100) div 100
l'approche n'a pas fonctionné pour moi, à cause de l'imprécision des points flottants. Par exemple, en multipliant 1.255 par 100 on obtient 125.499999999999 (cela ne signifie pas être dépendant de la mise en œuvre, comme c'est supposé être IEEE 754, mais je ne sais pas si toutes les implémentations adhèrent à cela). Lorsque arrondie, elle donne alors 125, plutôt que 126 désirée.
j'ai pris l'approche suivante, qui je pense fonctionne (bien que ce soit toujours un domaine délicat, donc je ne vais pas déclarer trop de confiance!). Cependant, cela dépend de votre moteur XSLT supportant les extensions EXSLT. Il suppose que vous voulez arrondir à deux décimales.
<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) > 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>
que l'on peut appeler comme:
<xsl:value-of select="local:RoundHalfUp(1.255)"/>
les namespaces sont:
xmlns:func="http://exslt.org/functions"
xmlns:estr="http://exslt.org/strings"
xmlns:local="http://www.acme.org/local_function"
il est important de noter que le la fonction ajoute '1', n'ajoute pas de 0,001 ou similaire.
Certainement préférable d'utiliser XSLT 2.0, si c'est une option (parce qu'il a un bon type décimal), mais je sais que c'est souvent pas une option (à partir de l'expérience douloureuse!).
par Rapport à toutes les réponses ci-dessus, j'ai trouvé
<xsl:value-of select="format-number(xs:decimal($quantity), '####0.00')" />
est utile, il ne tronque aucune valeur décimale. tronquer des nombres précis. si le numéro est dans le format Exponentiel, nous pouvons utiliser comme suit:
<xsl:value-of select="format-number(xs:decimal(number($quantity)), '####0.00')" />
Merci
j'ai également rencontré le problème selon lequel si vous avez ronde ($nombre * 100) div 100 vous obtenez une représentation à virgule flottante .4999999 et l'arrondissement ne fonctionne pas correctement.
pour contourner cela, cela semble fonctionner: ronde ($nombre * 1000 div 10) div 100