Last active
August 29, 2015 14:11
-
-
Save jmcastagnetto/1f06e295f13079db432d to your computer and use it in GitHub Desktop.
Implementation in PHP of the Kahan summation algorithm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// ref: http://rosettacode.org/wiki/Kahan_summation | |
// 1. Do all arithmetic in decimal to a precision of six digits. | |
// PHP does not have a way of restricting overall precision | |
// 2. Write a function/method/procedure/subroutine/... to perform Kahan | |
// summation on an ordered collection of numbers, (such as a list of numbers). ) | |
function kahansum($input) { | |
$sum = $c = 0; | |
foreach($input as $item) { | |
$y = $item + $c; | |
$t = $sum + $y; | |
$c = ($t - $sum) - $y; | |
$sum = $t; | |
} | |
return $sum; | |
} | |
// 3. Create the three numbers a, b, c equal to 10000.0, 3.14159, 2.71828 | |
// respectively. | |
$input = array(10000.0, 3.14159, 2.71828); | |
list($a, $b, $c) = $input; | |
// 4. show that the simple left-to-right summation, equivalent to (a + b) + c | |
// gives an answer of 10005.8 ) | |
$sumabc = ($a + $b) + $c; | |
echo "Main task - Left to right summation: "; | |
echo sprintf("%6.1f", $sumabc).PHP_EOL; | |
// 10005.9 | |
// 5. Show that the Kahan function applied to the sequence of values a, b, c | |
// results in the more precise answer of 10005.9 | |
echo "Main task - Kahan summation: "; | |
echo sprintf("%6.1f", kahansum($input)).PHP_EOL; | |
// 10005.9 | |
// Let's use the substask | |
$epsilon = 1.0; | |
while ((1.0 + $epsilon) != 1.0) { | |
$epsilon /= 2.0; | |
} | |
echo "Trying the subtask".PHP_EOL."epsilon: "; | |
echo $epsilon.PHP_EOL; | |
// 1.1102230246252E-16 | |
$a = 1.0; | |
$b = $epsilon; | |
$c = -$epsilon; | |
$input = array($a, $b, $c); | |
// left-to-right summation | |
$sumabc = ($a + $b) + $c; | |
echo "Sub task - Left to right summation: "; | |
echo sprintf("%f", $sumabc).PHP_EOL; | |
// kahan summation | |
echo "Sub task - Kahan summation: "; | |
echo sprintf("%f", kahansum($input)).PHP_EOL; | |
// but, are they really the same or is an artifact? | |
echo "Are the results the same?".PHP_EOL; | |
var_dump((($a + $b) + $c) === kahansum($input)); | |
// ok, then what is the difference? | |
echo "Difference between the operations: "; | |
$diff = (($a + $b) + $c) - kahansum($input); | |
echo $diff.PHP_EOL; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Main task - Left to right summation: 10005.9 | |
Main task - Kahan summation: 10005.9 | |
Trying the subtask | |
epsilon: 1.1102230246252E-16 | |
Sub task - Left to right summation: 1.000000 | |
Sub task - Kahan summation: 1.000000 | |
Are the results the same? | |
bool(false) | |
Difference between the operations: 1.1102230246252E-16 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment