xml - places - xsl value of select='' format number
XSL-problema de redondeo/nĂºmero de formato (4)
Estoy tratando de obtener el valor de un número a 2 dec lugares de mi xml.
XML: <Quantity>0.0050</Quantity>
XSL: <xsl:value-of select="format-number($quantity, ''####0.00'')" />
Sin embargo, XSL parece tener un problema con este valor y genera 0.00
en un área de la página y 0.01
en el otro. Por supuesto, en esta situación es favorable tener una producción de 0.01
en todas las áreas.
Otra área tiene el valor 4.221
pero el XSL está generando 4.23
.
Me doy cuenta de que el format-number
como método convierte un número en una cadena.
No estoy seguro de como arreglar esto.
EDITAR:
Ok después de un poco de rebuscar, encontré que esto funciona:
<xsl:value-of select=''format-number( round(100*$quantity) div 100 ,"##0.00" )'' />
A través de este website
Como este tipo menciona que XSL usa ''redondeo de banqueros'' para redondear a números pares en lugar de los números más grandes.
La solución apenas parece elegante, y significa agregar un montón de funciones adicionales a un archivo XSL ya voluminoso y complicado. Seguramente me estoy perdiendo algo?
En comparación con todas las respuestas anteriores que encontré
<xsl:value-of select="format-number(xs:decimal($quantity), ''####0.00'')" />
es útil, no está truncando ningún valor de punto decimal. truncando números exactamente especificados. si el número está en formato exponencial, podemos usarlo de la siguiente manera:
<xsl:value-of select="format-number(xs:decimal(number($quantity)), ''####0.00'')" />
Gracias
He tenido problemas interminables con los decimales en XSLT / XPath 1.0, a menudo una combinación de que representa los decimales como números de coma flotante y utilizando el redondeo a medias o incluso el redondeo del banquero. Desafortunadamente, el round(yournum*100) div 100
no funcionó para mí, debido a la imprecisión de coma flotante. Por ejemplo, multiplicar 1.255 por 100 da 125.49999999999999 (esto no debe depender de la implementación, ya que se supone que es IEEE 754, pero no sé si todas las implementaciones se adhieren a eso). Cuando se redondea, esto da 125, en lugar de los 126 deseados.
He tomado el siguiente enfoque, que creo que funciona (aunque esto siempre es un área difícil, ¡por lo que no declararé demasiada confianza!). Sin embargo, depende de que su motor XSLT sea compatible con las extensiones EXSLT. Supone que quieres redondear a dos decimales.
<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 se puede llamar así:
<xsl:value-of select="local:RoundHalfUp(1.255)"/>
Los espacios de nombres son:
xmlns:func="http://exslt.org/functions"
xmlns:estr="http://exslt.org/strings"
xmlns:local="http://www.acme.org/local_function"
Es importante tener en cuenta que la función agrega un ''1'', no agrega 0.001 o similar.
Definitivamente es mejor usar XSLT 2.0 si es una opción (porque tiene un tipo de decimal correcto), pero sé que a menudo eso no es una opción (¡por experiencia dolorosa!).
No estoy seguro de por qué el formato sería tan inconsistente, pero desde la memoria, la especificación es ... compleja.
Mientras tanto, puedes usar la función round
( ref ). Que es menos que perfecto, pero es funcional. ¡Si necesita tener un número particular de sig higos, puede usar THE POWER OF MATHS! y haz algo como:
<xsl:value-of select="round(yournum*100) div 100"/>
También he encontrado el problema por el cual si hiciste una ronda ($ number * 100) div 100 obtendrás una representación en coma flotante de .4999999 y el redondeo no funcionará correctamente.
Para evitar esto, esto parece funcionar: ronda ($ number * 1000 div 10) div 100