Kahan summation: Difference between revisions

Add Racket
(reworked the sample code to make it (hopefully) more understandable)
(Add Racket)
Line 524:
# TRUE
</lang>
 
=={{header|Racket}}==
Racket doesn't have arbitrary fixed precision numbers, but we can use single precision float point numbers that have approximately 8 decimal places. To reproduce the original task we have to replace the <code>10000.0</code> with <code>1000000.0</code>.
 
We then compare this result to the double precision result of the same numbers. The double precision numbers have almost 16 decimal places, so with <code>1000000.0</code> the usual summation nd the Kahan summation give the same result.
 
Finally we try the alternative task version for single precision float point numbers.
<lang Racket>#lang racket
 
(define (sum/kahan . args)
(define-values (sum c)
(for/fold ([sum 0] [c 0]) ([num args])
(define y (- num c))
(define t (+ sum y))
(values t (- (- t sum) y))))
sum)
 
(displayln "Single presition flonum")
(+ 1000000.0f0 3.14159f0 2.71828f0)
(sum/kahan 1000000.0f0 3.14159f0 2.71828f0)
 
(displayln "Double presition flonum")
(+ 1000000.0 3.14159 2.71828)
(sum/kahan 1000000.0 3.14159 2.71828)</lang>
{{out}}
<pre>Single presition flonum
1000005.8f0
1000005.9f0
Double presition flonum
1000005.85987
1000005.85987</pre>
 
Alternative task version
<lang Racket>(define epsilon.f0
(let loop ([epsilon 1.f0])
(if (= (+ 1.f0 epsilon) 1.f0)
epsilon
(loop (/ epsilon 2.f0)))))
 
(displayln "Alternative task, single precision flonum")
epsilon.f0
 
(+ 1.f0 epsilon.f0 (- epsilon.f0))
(sum/kahan 1.f0 epsilon.f0 (- epsilon.f0))</lang>
{{out}}
<pre>Alternative task, single precision flonum
5.9604645f-008
0.99999994f0
1.0f0</pre>
Anonymous user