[Tutor] generating independent random numbers

Carter Danforth carter.danforth at gmail.com
Tue Sep 28 23:11:05 CEST 2010


Thanks for the replies, Dave and Joel. The reason I'm not just using the
time or datetime modules for a random date is because it's restricted to
1970-2038; I'm pulling dates from 1600-3099. Thanks a lot for the pointer
about the leap years, Dave, as well the class instances; just updated it and
it's all working now, and also included the rest of the code too w/ answer
verification and time tracking.

I want to start using this program to test myself for speed calculation
using Zeller's formula, it's pretty cool for determining the days of dates -
http://mathforum.org/dr/math/faq/faq.calendar.html

Because of the way variables C and D are split up from the year in the
formula, I split up the year for self.c and self.y.

------------------------

import random, time, datetime, calendar

class Date:
    def __init__(self):
        self.c = random.randint(16,30)
        self.y = random.randint(0,99)
        self.month = random.randint(1,12)
        self.year = self.c*100 + self.y

        apr = [4,6,9,11]
        feb = [2]
        notleap = [1700, 1800, 1900, 3000]

        if self.month in feb:
            if self.year%4 == 0:
                if self.year in notleap:
                    self.k = random.randint(1,28)
                else:
                    self.k = random.randint(1,29)
            else:
                self.k = random.randint(1,28)
        elif self.month in apr:
            self.k = random.randint(1,30)
        else:
            self.k = random.randint(1,31)

        if self.month in [1,2]:
            d = self.y - 1
            m = self.month + 10
        else:
            d = self.y
            m = self.month - 2

        z = self.k + (13*m-1)/5 + d + d/4 + self.c/4 - 2*self.c

        if z < 0:
            r = (abs(z)/7)*7 + z + 7
        else:
            r = z%7

        dict = { 0: 'Sunday', 1: 'Monday', 2: 'Tuesday', 3: 'Wednesday', 4:
'Thursday', 5: 'Friday', 6: 'Saturday' }
        self.day = dict[r]

t1m = time.localtime().tm_min
t1s = time.localtime().tm_sec
t1 = t1m + t1s/100.0
n = 0
x = 0

while n < 10:
    newdate = Date()

    print '\n',calendar.month_name[newdate.month], newdate.k,',',
newdate.year,'=',
    answer = raw_input()
    if answer.capitalize() == newdate.day:
        pass
    else:
        x += 1
    n += 1

t2m = time.localtime().tm_min
t2s = time.localtime().tm_sec
t2 = t2m + t2s/100.0
td = t2 - t1

print '\n',x,'out of 10 wrong\nAvg time/question:',td/10,'\nTotal time:',td


On Mon, Sep 27, 2010 at 10:21 PM, Dave Angel <davea at ieee.org> wrote:

>
>
> On 2:59 PM, Steven D'Aprano wrote:
>
> On Tue, 28 Sep 2010 08:55:36 am Carter Danforth wrote:
>
>
>  class Date:
>     c = random.randint(16,30)
>     y = random.randint(0,99)
>     month = random.randint(1,12)
>
>  Here's your problem: you are creating a class where all the attributes
> (called "members" in some other languages) belong to the class and are
> shared by all instances.
>
> Python classes are themselves objects, and the code inside the class
> body gets executed *once*, when the class is created. So in this case,
> the Date class chooses a single random month, *once*, and all instances
> share this attribute Date.month.
>
> To get the behaviour you are after, you need to use instance attributes,
> which means referring to self. The usual place to do this is in the
> __init__ method, which is called when the instance is being
> initialised:
>
> class Date:
>     def __init__(self):
>         self.month = random.randint(1,12)
>         # etc.
>
>
>
> By the way, why do you calculate a century and year separately, then add
> c+y to get the year? It would be easier to just say:
>
> year = random.randint(1600, 3099)
>
>
>
>
>  That's the big problem, although it's also worth pointing out that you'll
> need a new instance each time through the loop.  It's not enough to call
> Date(), you also have to bind it to a name, and use that name for attribute
> lookup.    So something like
>     mydate = Date()
>     year = mydate.y + ....
>
> But there are at least a few subtle problems left.  One is that many of the
> years are divisible by four but do not have 29 days in February.  For
> example, 1800, 1900, 2100 are not leap years.
>
> Next problem is that the dates are not evenly distributed over the entire
> range of years.  The 14th of February will be more likely to be chosen than
> the sixth of July.  You can decide that this is deliberate, but it is a
> consideration.
>
> Third, the program doesn't do anything to check the user's answer.  For
> that matter, there's no timing going on either.
>
> Depending on the learning goals of this project, I'd consider using the
> datetime module, and method:
>
> mydate = date.fromordinal(*ordinal*)
>
> Now you can make a single randint() call, once you precalculate the
> starting and ending dates desired.   And this module also gives you other
> things you need, such as the weekday() method.
>
> DaveA
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tutor/attachments/20100928/d084885e/attachment-0001.html>


More information about the Tutor mailing list