[xsl] Re: format-number/bankers' rounding problem

Subject: [xsl] Re: format-number/bankers' rounding problem
From: daniel whitney <dbf.whitney@xxxxxxxxx>
Date: Wed, 13 Jul 2011 12:50:24 -0400
Sorry I should have started out by saying that I want positive decimal
values to round up and negative decimal values to round down.

On Wed, Jul 13, 2011 at 12:28 PM, daniel whitney <dbf.whitney@xxxxxxxxx>
wrote:
> I saw the round solution on the web, details below...
>
> Java v. 1.6.0_26-b03
> Saxon v. 9.1.0.8J
> XSL version="1.0"
>
> I hit the problem of bankers' rounding when performing a transform
> using Java and Saxon and I think I have a solution that works, but I
> wanted to see if my logic is questionable.
>
> Some background:
>
> To do transforms we use Java, Microsoft and PHP based processors. When
> using format-number('0.165', '0.00') the output returned is 0.16
> (Java), 0.17 (MS) and 0.17 (PHP). I looked on the web for a solution
> to this and saw the round solution. I tried it on a small sample of
> data and it looked OK but then noticed something strange. With this:
> <xsl:value-of select="format-number(round('0.145' * 100) div 100,
> '0.00')"/>, using Saxon, the result is 0.14. Other numbers like 0.165
> (0.17), or even trying this: format-number(round('0.0145' * 1000) div
> 1000, '0.000') (0.015), worked.
>
> This also presented another problem. We use an XSL called  template to
> format most of our numbers. Parameters it accepts are, of course, the
> number, formatting for positive numbers, formatting for negative
> numbers, minimum number of decimals and maximum number of decimals. If
> I were to use the round number, I would have to write something to
> deal with whether to use 100, 1000, 10000 etc to round. Not a huge
> deal but .... The clincher though was when I tested the rounding on
> negative numbers: <xsl:value-of select="format-number(round('-0.165' *
> 100) div 100, '(0.00)')"/> (using Saxon) produces "(0.16)". So that
> was the nail in the coffin for round.
>
> So what I came up with was just to append '0000001' to the original
> decimal (there's already a separate formatting condition for values
> with no decimal) and then to format that:           <xsl:value-of
> select="format-number(concat($numberValueParam,
> '0000001'),$formatNumberVar)"/>
>
> So if $numberValueParam = '0.145' and $formatNumberVar is
> '0.00;(0.00)' the value I'm formatting is '0.1450000001' and produces
> the output 0.15 and works for both positive and negative values.
>
> I concatenate so many 0's as the maximum number of decimals we might
> display is 6 and I wanted to ensure that '0.2' would output as
> '0.200000' and not '0.200001'.
>
> This solution is simple for me to implement, so, is there a flaw in my
> logic? Better, does something already exist where I can just indicate,
> round up for positive and down for negative values?
>
> Thanks for any input,
>
> Dan.

Current Thread