Discussion:
rounding within the "format-number" function
Osheka, Susan
2006-01-26 16:03:58 UTC
Permalink
What I have noticed is that the XSL "format-number" function rounds to
the nearest even number, instead of the bigger one, as is usual and
would be expected. According to one site, this is sometimes called
"banker's rounding."
Its purpose is to eliminate the slight bias that occurs when always
rounding upwards.
I am using XSLT 1.0.

For example : 9.2750 rounds up to 9.28, but 9.2850 rounds down to 9.28
.
9.2950 rounds up to 9.30, but 9.3050 rounds down to 9.30.

Here is the XSLT I am using: <xsl:value-of
select="format-number($number,'##.00')"/>

On our pages, we want to always round up to two decimal places, and I
don't want to lose the formatting. I would want 9.2850 to round up to
9.29. The solution that I have come up with is:

<xsl:value-of select='format-number( round(100*$number) div 100 ,
"##.00" )'

Do you have a better solution?? Is there anyway to globally change the
default rounding (banker's rounding) to always round up???


--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-***@lists.mulberrytech.com>
--~--
Michael Kay
2006-01-26 16:50:28 UTC
Permalink
Post by Osheka, Susan
What I have noticed is that the XSL "format-number" function
rounds to
the nearest even number, instead of the bigger one, as is usual and
would be expected. According to one site, this is sometimes called
"banker's rounding."
Its purpose is to eliminate the slight bias that occurs when always
rounding upwards.
I am using XSLT 1.0.
Technically I don't think that XSLT 1.0 defines the rounding algorithm. It
defines format-number() in terms of the JDK 1.1 specification, and the JDK
1.1 specification didn't actually say what the rounding rules were. XSLT
implementations written in Java probably used the underlying JDK class
library, which did "banker's rounding", but implementations in other
languages might have used a different algorithm. XSLT 2.0 defines the rules
as you describe.
Post by Osheka, Susan
On our pages, we want to always round up to two decimal places, and I
don't want to lose the formatting. I would want 9.2850 to round up to
<xsl:value-of select='format-number( round(100*$number) div 100 ,
"##.00" )'
Do you have a better solution?? Is there anyway to globally change the
default rounding (banker's rounding) to always round up???
No, and no. (Not even in 2.0!)

Michael Kay
http://www.saxonica.com/



--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-***@lists.mulberrytech.com>
--~--
David Carlisle
2006-01-26 16:57:23 UTC
Permalink
Post by Michael Kay
No, and no. (Not even in 2.0!)
xpath2 defines round() to round up and round-half-to-even() to to
rounding-as-i-was-taught-at-school doesn't it?

David

________________________________________________________________________
This e-mail has been scanned for all viruses by Star. The
service is powered by MessageLabs. For more information on a proactive
anti-virus service working around the clock, around the globe, visit:
http://www.star.net.uk
________________________________________________________________________

--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-***@lists.mulberrytech.com>
--~--
David Carlisle
2006-01-26 17:00:50 UTC
Permalink
MK> No, and no. (Not even in 2.0!)

DC> xpath2 defines round() to round up and round-half-to-even() to to
DC> rounding-as-i-was-taught-at-school doesn't it?

what I said is true, but not directly related to either of Michael's
"No" as they are about format-number rather than round().

David

________________________________________________________________________
This e-mail has been scanned for all viruses by Star. The
service is powered by MessageLabs. For more information on a proactive
anti-virus service working around the clock, around the globe, visit:
http://www.star.net.uk
________________________________________________________________________

--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-***@lists.mulberrytech.com>
--~--
Michael Kay
2006-01-26 17:48:25 UTC
Permalink
Post by David Carlisle
Post by Michael Kay
No, and no. (Not even in 2.0!)
xpath2 defines round() to round up and round-half-to-even() to to
rounding-as-i-was-taught-at-school doesn't it?
You were obviously at a better school than most people.

We do offer a selection of algorithms, but not everything that anyone wants
(e.g. rounding away from zero); and the only one that does rounding to a
user-specified number of decimal places is round-half-to-even(), which uses
one particular algorithm.

Michael Kay
http://www.saxonica.com/



--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-***@lists.mulberrytech.com>
--~--

Haarman, Michael
2006-01-26 17:30:20 UTC
Permalink
From: Michael Kay
Post by Osheka, Susan
What I have noticed is that the XSL "format-number" function
rounds to
the nearest even number, instead of the bigger one, as is usual and
would be expected. According to one site, this is sometimes called
"banker's rounding."
implementations written in Java probably used the underlying JDK class
library, which did "banker's rounding", but implementations in other
languages might have used a different algorithm. XSLT 2.0
defines the rules
as you describe.
It may be that what OP is witnessing is an artifact of floating point
calculations returning something like .49999999 and rounding down.
Post by Osheka, Susan
<xsl:value-of select='format-number( round(100*$number) div 100 ,
"##.00" )'
Isn't it the case that this can still fail, only quite a bit less
frequently? To ensure correct up-rounding, use this:

<xsl:value-of select="format-number(ceiling(100 * $number)
div 100, '##.00')"/>



HTH,

-----------------------------------
Mike Haarman,
XSL Developer,
Internet Broadcasting Systems, Inc.

--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-***@lists.mulberrytech.com>
--~--
Haarman, Michael
2006-01-26 17:43:00 UTC
Permalink
From: Haarman, Michael
It may be that what OP is witnessing is an artifact of floating point
calculations returning something like .49999999 and rounding down.
Post by Osheka, Susan
<xsl:value-of select='format-number( round(100*$number) div 100 ,
"##.00" )'
Isn't it the case that this can still fail, only quite a bit less
<xsl:value-of select="format-number(ceiling(100 * $number)
div 100, '##.00')"/>
Forgive the reply to myself. I'd ask you to ignore the bit of dumbness
exposed above. ceiling() is a mistake here.

It remains true that round() can occasionally expose the vagaries of
floating point math.


Mike

--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-***@lists.mulberrytech.com>
--~--
Loading...