On Sun, Feb 3, 2013 at 6:31 PM, kirby urner <span dir="ltr"><<a href="mailto:kirby.urner@gmail.com" target="_blank">kirby.urner@gmail.com</a>></span> wrote:<br><div class="gmail_quote"><div><br><< SNIP >><br>
 <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Your idea to do fractions, to build them from the inside out, is a<br>
good idea.  You could start with Guido's record-simple GCD function,<br>
for Euclid's Algorithm, then gradually build out with __add__, __mul__<br>
etc. using these inside a class (you can call out to them).<br>
<br>
def gcd(a, b):<br>
    while b:<br>
        a, b = b, a % b<br>
    return a<br>
<br>
def lcm(a, b):<br>
    return ( a * b ) // gcd(a, b)<br>
<br>
The thing about Euclid's Algorithm is it's barely taught at all in<br>
high schools, and if you ask why, then you've again jumped into a<br>
rather deep discussion, deeper than just computers.<br>
<br></blockquote><div><br>As I was mentioning to Dan off-list, it's the Closure property of Rational numbers (rats) under both addition-subtraction and multiplication-division, that makes them such pleasing mathematical objects.  <br>
<br>Yes, the whole numbers and naturals (N) are closed under addition too, but then there're no inverses except for zero.  <br><br>With Z we get both inverses and closure (operation addition).  Associativity.<br><br>With Q, we get that for two operations (__add__ and __mul__), and distributivity besides.  <br>
<br>Our first field maybe.<br><br>But to really show that, you want to be able to give birth to Fractions with fractions as inputs:<br><br>>>> p = Rat(1,2)<br>>>> q = Rat(4,3)<br>>>> r = Rat(p, q)<br>
<br>This shows allowing both int type and rat type as inputs.  <br><br>I think that's a fine place to draw the line, in terms of introducing basic type checking.  I've seen blogs about how "isinstance is evil in a duck pond" but I'm fine with type checking.  Python is dynamically typed, not weakly typed.<br>
<br>So that puts the burden on __init__ to be sophisticated enough to birth new Rationals from any two Rationals.  ints are immediately recognized as Rat(n, 1).  The set int (Z) is a subset of Q.<br><br>That, by the way, is how to make this seem more like math teaching, not just computer science teaching.  Remind students about N < Z < Q < R < C (which is not the whole story).<br>
<br>Operator overriding is what makes for a sophisticated turn of the spiral around the 8th or 9th grade reading level.  <br><br>You realize that __add__ and __mul__ may be defined for many types, and yet there's a family resemblance that emerges:  the property of having an identity element; the property of having and inverse element for each element, such that self + ~self == Identity element.<br>
<br>In addition to the Rats, I like to introduce numbers that multiply modulo N, could be called the Modulo Numbers.  That's just repackaging well known content, using the OO approach of "math objects".<br><br>
Take the totatives of a number N and make them multiply module N:  you've got closure, associativity, identity and inverse elements, every time.  That's a group.  Welcome to abstract algebra, courtesy of __mul__.<br>
<br>def totatives(n):<br>    return [ r for r in range(1, n) if gcd(r, n) == 1]  #  gcd defined above<br><br>def totient(n):<br>    return len(totatives(n))<br><br>>>> totatives(12)<br>[1, 5, 7, 11]<br>>>> totatives(100)<br>
[1, 3, 7, 9, 11, 13, 17, 19, 21, 23, 27, 29, 31, 33, 37, 39, 41, 43, 47, 49, 51, 53, 57, 59, 61, 63, 67, 69, 71, 73, 77, 79, 81, 83, 87, 89, 91, 93, 97, 99]<br><br><br>I've got a web page called Vegetable Group Soup with more about all this but I won't give the URL, because there's a nasty noise, like a machine at a factory, and you might be wearing headphones.<br>
<br>Kirby<br><br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
The Litvins books starts to build a Fraction but mostly eschews<br>
defining classes.<br>
<br>
A "classes early" approach is also doable -- many different approaches<br>
to this airport, pick your vector.<br>
<br>
I show how a class looks something like a snake:<br>
<br>
class Head:<br>
    # rib cage<br>
    def __rib__(self):<br>
        pass  # air between ribs<br>
    def __rib__(self):<br>
        pass<br>
    def __rib__(self):<br>
        pass<br>
    def __rib__(self):<br>
        pass<br>
    def __rib__(self):<br>
        pass<br>
<br>
... and in general use a lot of biological metaphors / analogies.<br>
<br>
<br>
Kirby<br>
<br>
Web resources:<br>
<br>
<a href="http://www.4dsolutions.net/ocn/numeracy0.html" target="_blank">http://www.4dsolutions.net/ocn/numeracy0.html</a><br>
<a href="http://www.4dsolutions.net/ocn/cp4e.html" target="_blank">http://www.4dsolutions.net/ocn/cp4e.html</a><br></blockquote><div><br> </div></div>