[prev in list] [next in list] [prev in thread] [next in thread] 

List:       fop-user
Subject:    Re: AW: marker value to variable [SOLVED]
From:       Andreas L Delmelle <a_l.delmelle () pandora ! be>
Date:       2006-07-25 19:13:41
Message-ID: 64A72AC6-A9DD-4D75-92A9-4BF17A080F3F () pandora ! be
[Download RAW message or body]

On Jul 25, 2006, at 12:05, Alexander Schwartz wrote:

Hi,

> One thing when doing calculations in XSL:
>
> All these numbers are floats, therefore every calculation may give  
> you unexpected rounding errors.

True, but then again, this is not specific to XSL...

As you are probably aware, on the level of the hardware/machine code,  
there is strictly speaking no such thing as a precise and exact  
division. Not like we would expect, anyway. This is especially true  
when the resulting float does not have a finite number of decimal  
digits, but even one decimal digit is enough.

Digits on the right-hand side of the decimal separator represent a  
negative power of ten (or 'one divided by a power of ten'), which  
makes it quite impossible for certain rational decimal numbers to be  
expressed as binary floats without doing some sort of approximation

Take the simplest decimal 0.1 (= 1 * 10^-1):
8 bits can get you awfully close, but you'd need more not to round.

* 0.1 in binary = 1/2 = 0.5 in decimal
* 0.01 = 1/4 = 0.25
* 0.001 = 1/8 = 0.125
* 0.0001 = 1/16 = 0.0625

The decimal value 0.1 seems to lie somewhere between 0.001 and 0.0001 :)

* 0.00001 = 1/32 = 0.03125 (+ 0.0625 = 0.09325)
* 0.0000001 = 1/256 = 0.00390625 (+ 0.09325 = 0.09715625)

The only accurate way to express it in binary, without losing  
precision, is as a fraction/division (= binary one divided by binary  
ten = 1/110).

BTW: IIRC, there are languages around that store rational numbers as  
fractions --LISP to name one--, the divisions are only actually  
performed if the value needs to be displayed in decimal notation.

> http://www.w3.org/TR/xpath#section-Number-Functions
>
> Is there a way to avoid this?

If you know in advance how many significant digits you need, you  
could always multiply by a power of ten and truncate or round  
yourself, so that those digits end up _before_ the decimal separator,  
and you would always deal with integers.

I guess, in a way, this roughly resembles what most computers/ 
calculators do: treat the whole number as if it were an integer -- 
remove the separator, and only *after* adding/subtracting/dividing/ 
multiplying, sort out where the decimal separator needs to end up.
IOW: if you make sure you compute only with integers, that can be  
converted from decimal to binary back and forth without any rounding  
in between, you'll be reasonably safe.

OTOH, if your starting point is a float of arbitrary precision,  
you'll always run the risk of rounding being introduced somewhere,  
beginning with the first conversion from decimal to binary.

That said, floor() and ceiling() are guaranteed to return an integer,  
and I guess there would be very few XSLT implementations around that  
can't handle precision up to four digits, but this is only a guess.
The real problems would start when you need to be so precise that  
multiplication by the appropriate power of ten could easily cause  
integer overflow...


Hope this --helps? :/


Cheers,

Andreas

---------------------------------------------------------------------
To unsubscribe, e-mail: fop-users-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-users-help@xmlgraphics.apache.org

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic