Author: Odd Gunnar Malin
Date: 13:38:03 04/20/05
Go up one level in this thread
On April 20, 2005 at 11:25:05, Eelco de Groot wrote:
>Hello Gunnar,
>
>I don't know if you would want to try to convert this from Pascal to C but the
>advantage is it doesn't use a table-lookup but an iterative procedure.
>
>Anyway, it was good to get a look at some old Pascal listings again and try to
>write something new. I suppose C has a function somewhere to calculate area
>under the Normal distribution, error function erf(), Excel has it for sure. That
>could be used instead of FUNCTION phi() C. Not versed in C and my Pascal is very
>rusty, but I think this should work with an iterative procedure instead of a
>table lookup.
>
>I had to reconstruct from memory what my Casio calculator routine did and
>haven't tested the code below in Pascal yet. The phi() funcition should work, I
>converted it years ago from the manual for my old Casio FX 501P, it uses
>Hastings best approximation for the area under the bellcurve of the normal
>distribution. In the original calculator program I believe I used Simpson's rule
>to approximate the area.
>
>In good old Turbo Pascal:
>
>(* sndf stands for standard normal density function. *)
>(* phi is the integral of minus infinity to t of function ø(t)dx, where ø(t) =
>(1/square root(2*Pi))*e^-(x^2/2). *)
>(* Pi=3.14159265358979..... etc. *)
>(* Performance is a number between 0 and 1, scoringpercentage divided by 100. *)
>(* Rtdiff is the rating difference that you want to calculate given Performance
>*)
>
>FUNCTION phi(x:REAL):REAL;
>CONST p=0.2316419;
> c1=0.31938153;
> c2=-0.356563782;
> c3=1.78147937;
> c4=-1.821255978;
> c5=1.330274429;
>VAR t,sndf:REAL;
>BEGIN
> sndf:=EXP(-SQR(x)/2)/SQRT(2*PI);
> t:=1/(p*x+1);
> phi:=((((c5*t+c4)*t+c3)*t+c2)*t+c1)*t*sndf;
>END;
>
>FUNCTION Rtdiff(Performance:REAL):REAL;
>CONST tol=0.0001;
> sdev=200*SQRT(2);
>VAR delta:REAL;
>BEGIN
> Rtdiff:=(Performance-0.50)*700;
> delta:=1;
> WHILE delta >= tol DO BEGIN
> Iteration:=phi(Rtdiff/sdev);
> delta:=Performance-Iteration;
> Rtdiff:=Rtdiff+(delta*700);
> END;
>END;
Hi.
Its easy enough to translate it to c(++) but I get a endless loop in there.
If I set:
Iteration=phi(-rtdiff/sdev);
instead of
Iteration=phi(rtdiff/sdev);
I get some numbers that make sense. The value at 0,90 is 358 so it is better
than the log10 algorithm (but Schmitt's algorithm is still better :) ).
I don't have the helpfiles here to see how to compile it with better precision
(81 bits real) so I do a new compile to morrow to see if I get any difference.
#include <iostream>
#include <cmath>
long double phi(long double x)
{
long double p,c1,c2,c3,c4,c5,t,sndf,pi;
p=0.2316419;
c1=0.31938153;
c2=-0.356563782;
c3=1.78147937;
c4=-1.821255978;
c5=1.330274429;
pi=3.1415926535897932384626433832795;
sndf= exp(-pow(x,2.0)/2.0)/sqrt(2.0*pi);
t=1/(p*x+1);
return (((((c5*t+c4)*t+c3)*t+c2)*t+c1)*t*sndf);
}
long double Rtdiff(long double Performance)
{
long double tol,sdev,delta,rtdiff,Iteration;
tol=0.0001;
sdev=200*sqrt(2);
rtdiff=(Performance-0.5)*700;
delta=1.0;
while (delta>=tol)
{
// Iteration=phi(rtdiff/sdev); // Iteration goes towards 0
Iteration=phi(-rtdiff/sdev); // With -rtdiff it goes towards Performance
delta=Performance-Iteration;
rtdiff+=delta*700;
};
return rtdiff;
}
// Test
int main(int argc, char* argv[])
{
long double score=0.01;
while (score<1.0)
{
std::cout << score << ": " << (int)(Rtdiff(score)+0.5) << std::endl;
score+=0.01;
}
return 0;
}
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.