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.