You want to
round to a specific number of decimal places; however,
XSLT’s round
,
ceiling
, and floor
functions
always map numbers to integer values.
Multiply, round, and divide using a power of ten that determines how
many decimal digits are required. Assuming $pi
=
3.1415926535897932:
<xsl:value-of select="round($pi * 10000) div 10000"/>
results in 3.1416. Similarily:
<xsl:value-of select="ceiling($pi * 10000) div 10000"/>
results in 3.1416, and:
<xsl:value-of select="floor($pi * 10000) div 10000"/>
results in 3.1415.
Rounding to a specific number of decimal places is also achieved
using
format-number( )
:
<xsl:value-of select="format-number($pi,'#.####')"/>
This results in 3.1416. This will work even if more than one
significant digit is in the whole part because
format-number
never uses a format specification as
an indication to remove significant digits from the whole part:
<xsl:value-of select="format-number($pi * 100,'#.####')"/>
This results in 314.1593.
You can use format-number
to get the effect of
truncating rather than rounding by using one more formatting digit
than required and then chopping off the last character:
<xsl:variable name="pi-to-5-sig" select="format-number($pi,'#.#####')"/> <xsl:value-of select="substring($pi-to-5-sig,1,string-length($pi-to-5-sig) -1)"/>
This results in 3.1415.
This multiply, round, and divide technique works well as long as the numbers involved remain within the representational limits of IEEE floating point. If you try to capture too many places after the decimal, then the rules of IEEE floating point will interfere with the expected result. For example, trying to pick up 16 decimal digits of pi will give you only 15:
<xsl:value-of select="round($pi * 10000000000000000) div 10000000000000000"/>
This results in 3.141592653589793, not 3.1415926535897932.
An alternative technique manipulates the number as a string and truncates:
<xsl:value-of select="concat(substring-before($pi,'.'), '.', substring(substring-after($pi,'.'),1,4))"/>
and results in 3.1415.
The effect of ceiling or round can be obtained by this technique at the cost additional complexity.
<xsl:variable name="whole" select="substring-before($pi,'.')"/> <xsl:variable name="frac" select="substring-after($pi,'.')"/> <xsl:value-of select="concat($whole, '.', substring($frac,1,3), round(substring($frac,4,2) div 10))"/>
This results in 3.1416.