More accurate summations [was Re: This math scares me]
Edward Jason Riedy
ejr at cs.berkeley.edu
Fri Mar 16 22:43:57 EST 2001
And <jurgen.defurne at philips.com> writes:
-
- Try summing all financial operations of one day together, or
- better, all operations involving percentages and then adding them
- together : cumulative errors.
More concretely, look at the Vancouver Stock Exchange index's
problems of the late 70s-early 80s. They had chosen to truncate
floating point values rather than round them, causing a downward
drift of around 20 points a month[1].
You could say that's because of poor handling of floating-point
arithmetic, and you'd be right. However, just about every inaccuracy
in floating-point financial calculations can be attributed to poor
handling of fp arithmetic.
That doesn't mean floating point is a poor choice for all financial
programs. Indeed, the HP financial calculators _all_ use floating
point, although decimal. Those calculators were designed twenty-odd
years ago, and they're still selling for almost as much as a Pilot.
If you want a _very_ accurate sum for all the operations in one day,
use the following algorithm. It is often attributed to Kahan, but,
if I recall his comments correctly, he's not entirely sure of the
origins of the embodied idea. Other names around this style of
algorithm are Moller (with a backwards slash through the o), Dekker,
Pichat, Knuth, Bohlender, and Linnainmaa in no particular order.
That's a surprising number of people for just adding numbers. ;)
class DistilledSum:
"Keep an accurate running sum."
def __init__ (self):
self.s = 0.0
self.c = 0.0
def add (self, x):
"Incorporate x into the running sum."
y = x - self.c
t = self.s + y
self.c = (t - self.s) - y
self.s = t
def value (self):
"Return the sum itself."
return self.s
def asTuple (self):
"Return both the sum and the error term."
return (self.s, self.c)
The accumulated error in s from floating-point calculations is at
most one unit in the last place of each summand x, and the value of
c gives you a tighter bound on that error. With not entirely
horrible amounts of extra work, you can have however much precision
you need[2]. Unless your numbers are horribly scaled (perhaps the
debt and GNPs of the entire globe along with a person's), this in
double plus rounding the stored answer to float works wonders for
financial accumulations.
You can find an explanation of how this works either in [2] or [3].
Essentially, the self.c term serves as a small correction. The
trick with (t - self.s) - y first zeros the high-order bits that
are shared between the old and new sum, then zeros the bits shared
with the pre-corrected x, giving a new correction.
Jason, unsure of how to create other languages' characters from
this particular keyboard...
[1] Q20 at http://catless.ncl.ac.uk/Risks/3.41.html#subj4.1
[2] http://citeseer.nj.nec.com/priest92propertie.html
[3] http://www.validlab.com/goldberg/paper.ps
--
More information about the Python-list
mailing list