#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    76
    Rep Power
    2

    Floating Point Math: Not according to plan


    So, I've been trying to develop a Python program to deal with Elo chess ratings. A fully detailed explanation of the math involved can be found at:

    http://en.wikipedia.org/wiki/Elo_rating_system

    Here is my code so far:
    Code:
    class player():
            name = str()
            rating = int ()
            records = list()
            def __init__(self,plname = 'PLAYER',prescore = 100):
                    self.name = plname
                    self.rating = prescore
            def __repr__(self):
                    return self.name+':'+str(self.rating)
            def ratings_update(self,kFactor=24):
                    ext,act=int(),int()
                    for rec in self.records:
                            ext += rec[0]
                            act += rec[1]
                    self.rating = int(self.rating + kFactor(act-ext))
                    self.records = list()
    
    def prediction(plA,plB,magTen=400):
    	estA = float( 1/(1+(10**((plA.rating-plB.rating)/magTen))) )
    	estB = float( 1/(1+(10**((plB.rating-plA.rating)/magTen))) )
    	estA,estB = round(estA,4),round(estB,4)
    	return [estA,estB]
    
    testA=player('Joe',1500)
    testB=player('Jim',1600)
    testC=player('Jack',1730)
    No matter which player combination you request a score for, the result only fluctuates between an effective 1 and 0.

    I can't figure out where I mussed up the formula. It should integrate correctly, but I know that floats always seem to have issues like this.

    Any help?
  2. #2
  3. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2012
    Location
    39N 104.28W
    Posts
    158
    Rep Power
    3
    For example, you have:
    estA = float( 1/(1+(10**((plA.rating-plB.rating)/magTen))) )

    Look at what that does: it casts the result of integer arithmetic (assuming that you're raising 10 to an integer power) to a float. All that does is add ".00" to an integer. You need to do the casting before the division. So instead of "1/..." you can have "1.0/..." or "float(1)/..." if you prefer.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2009
    Posts
    485
    Rep Power
    33
    You don't ever change "ratings" so they are still 1500, 1600, and 1730 which will yield a 0 to 1 result. You don't ever call ratings_update() so nothing ever changes. Also, there are no records in self.records so the for loop never executes. I would suggest that you add some print statements along the way so you can see what executes and what values are affected. Finally, is kFactor supposed to be an integer
    Code:
            def ratings_update(self,kFactor=24):
    or a function()
    Code:
                    self.rating = int(self.rating + kFactor(act-ext))
    Last edited by dwblas; March 11th, 2013 at 08:16 PM.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    76
    Rep Power
    2
    @rrashkin: Thanks. I probably should have realized that earlier. XD I'll implement it when I get back to this in awhile and report back if I have any further problems.

    UPDATE: Works like a charm. Thank you rrashkin!

    @dwblas: That's great and all, but as I stated before, the code was incomplete. The reason the ratings exist is because they ARE subject to change, I just haven't implemented that yet. Likewise, the players DO need instance attributes. I'm working with more than one instantiated player.
    I mean you no disrespect but I can't help but feel as if you didn't even read the actual question I posed.

IMN logo majestic logo threadwatch logo seochat tools logo