Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: Slide rules at the ready! Re: Rough approximation Re: ELO Calculations

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.