Kahan summation: Difference between revisions

From Rosetta Code
Content added Content deleted
(Example implementation in R, with comparison to the standard sum() implementation)
m (added the a+b+c code)
Line 66: Line 66:
> # make R display more digits in the result
> # make R display more digits in the result
> options(digits=10)
> options(digits=10)
> a <- 10000.0
> b <- 3.14159
> c <- 2.71828
> a + b + c
[1] 10005.85987
> # no problem there
> input <- c(10000.0, 3.14159, 2.71828)
> input <- c(10000.0, 3.14159, 2.71828)
> kahansum(input)
> kahansum(input)
[1] 10005.85987
[1] 10005.85987
> # compare with the standard sum() function
> # for completeness, let's compare with the standard sum() function
> sum(input)
> sum(input)
[1] 10005.85987
[1] 10005.85987
> # seems like R does the "right thing"
> # seems like R does the "right thing"
> # bonus:
> # let's use the Dr. Dobbs example (http://www.drdobbs.com/floating-point-summation/184403224)
> # let's use the Dr. Dobbs example (http://www.drdobbs.com/floating-point-summation/184403224)
> input <- c(1.0, 1.0e10, -1.0e10)
> input <- c(1.0, 1.0e10, -1.0e10)

Revision as of 20:40, 11 December 2014

Kahan summation is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

The Kahan summation algorithm is a method of summing a series of numbers represented in a limited precision in a way that minimises the loss of precision in the result.

The task is to follow the previously linked Wikipedia articles algorithm and its worked example by:

  1. Do all arithmetic in decimal to a precision of six digits.
  2. Write a function/method/procedure/subroutine/... to perform Kahan summation on an ordered collection of numbers, (such as a list of numbers).
  3. Create the three numbers a, b, c equal to 10000.0, 3.14159, 2.71828 respectively.
  4. Show that the simple left-to-right summation, equivalent to (a + b) + c gives an answer of 10005.8
  5. Show that the Kahan function applied to the sequence of values a, b, c results in the more precise answer of 10005.9

Show all output on this page.

Python

<lang python>>>> from decimal import * >>> >>> getcontext().prec = 6 >>> >>> def kahansum(input):

   summ = c = 0
   for num in input:
       y = num - c
       t = summ + y
       c = (t - summ) - y
       summ = t
   return summ

>>> a, b, c = [Decimal(n) for n in '10000.0 3.14159 2.71828'.split()] >>> a, b, c (Decimal('10000.0'), Decimal('3.14159'), Decimal('2.71828')) >>> >>> (a + b) + c Decimal('10005.8') >>> kahansum([a, b, c]) Decimal('10005.9') >>> >>> >>> sum([a, b, c]) Decimal('10005.8') >>> # it seems Python's sum() doesn't make use of this technique. >>> >>> # More info on the current Decimal context: >>> getcontext() Context(prec=6, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[Inexact, Rounded], traps=[InvalidOperation, DivisionByZero, Overflow]) >>> >>> >>> ## Lets try the simple summation with more precision for comparison >>> getcontext().prec = 20 >>> (a + b) + c Decimal('10005.85987') >>> </lang>


R

<lang> > # A straightforward implementation of the algorithm > kahansum <- function(x) { + ks <- 0 + c <- 0 + for(i in 1:length(x)) { + y <- x[i] - c + kt <- ks + y + c = (kt - ks) - y + ks = kt + } + ks + } > # make R display more digits in the result > options(digits=10) > a <- 10000.0 > b <- 3.14159 > c <- 2.71828 > a + b + c [1] 10005.85987 > # no problem there > input <- c(10000.0, 3.14159, 2.71828) > kahansum(input) [1] 10005.85987 > # for completeness, let's compare with the standard sum() function > sum(input) [1] 10005.85987 > # seems like R does the "right thing" > # bonus: > # let's use the Dr. Dobbs example (http://www.drdobbs.com/floating-point-summation/184403224) > input <- c(1.0, 1.0e10, -1.0e10) > kahansum(input) [1] 1 > sum(input) [1] 1 > # again, R does it right </lang>