Kahan summation: Difference between revisions

→‎{{header|REXX}}: added a tweaked version for later versions of Regina (3.4 and later).
m (→‎{{header|REXX}}: right justify numbers (A,B,C) if non-negative.)
(→‎{{header|REXX}}: added a tweaked version for later versions of Regina (3.4 and later).)
Line 577:
Programming note: &nbsp; It wasn't clear what precision to use for the 2<sup>nd</sup> part of this task, so an arbitrary precision
<br>of &nbsp; '''30''' &nbsp; (decimal digits) was chosen. &nbsp; The default precision for REXX is &nbsp; '''9''' &nbsp; decimal digits.
===vanilla version===
 
<lang rexx>/*REXX program demonstrates simple addition versus using Kahan summation*/
numeric digits 6 /*use numeric (decimal) digits=6.*/
Line 688:
simple summation of a,b,c = 1.00000000000000000000000000000
Kahan summation of a,b,c = 1.00000000000000000000000000000
 
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
</pre>
 
===tweaked version===
The following tweaked REXX version causes Regina (3.4 and later) to work properly/
<lang rexx>/*REXX program demonstrates simple addition versus using Kahan summation*/
numeric digits 6 /*use numeric (decimal) digits=6.*/
call show 10000.0, 3.14169, 2.71828 /*invoke SHOW to sum and display.*/
 
numeric digits 30
epsilon=1.0
do while 1.0+epsilon \= 1.0
epsilon=epsilon / 2.0
end /*while*/
/* [↓] for Regina 3.4 and later.*/
numeric digits digits()+2 /*bump the precision by 2 digits.*/
call show 1.0, epsilon, -epsilon /*invoke SHOW to sum and display.*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────KAHAN subroutine────────────────────*/
kahan: procedure; sum=0; c=0
do j=1 for arg() /*do for each arg.*/
y=arg(j)-c /*sub C from arg. */
t=sum+y /*use a temp sum. */
c=(t-sum)-y /*same as: t-sum-y*/
sum=t /*define the sum. */
end /*j*/
return sum
/*──────────────────────────────────SHOW subroutine─────────────────────*/
show: procedure; parse arg a,b,c /*obtain the args.*/
say 'decimal digits =' digits() /*show # dec digs.*/
say ' a = ' left('', a>=0) a /*show A justified*/
say ' b = ' left('', b>=0) b /* " B " */
say ' c = ' left('', c>=0) c /* " C " */
say 'simple summation of a,b,c = ' (a+b)+c /*same as a+b+c */
say 'Kahan summation of a,b,c = ' kahan(a,b,c) /*sum via Kahan. */
say; say copies('▒',70); say /*display a fence.*/
return</lang>
'''output''' for Regina 3.4 and later versions:
<pre>
decimal digits = 6
a = 10000.0
b = 3.14169
c = 2.71828
simple summation of a,b,c = 10005.8
Kahan summation of a,b,c = 10005.9
 
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
 
decimal digits = 32
a = 1.0
b = 3.15544362088404722164691426133E-30
c = -3.15544362088404722164691426133E-30
simple summation of a,b,c = 1.0000000000000000000000000000001
Kahan summation of a,b,c = 1.0000000000000000000000000000000
 
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒