[Edu-sig] Python 2.0 and teaching precalculus
Kirby Urner
urner@alumni.Princeton.EDU
Sun, 10 Sep 2000 02:01:59 -0700
Keywords: Python 2.0, cli, precalc, discrete math, graphing, domain,
range, function, povray, derivative, epsilon, ocn
Originally posted to: edu-sig@python.org (list), comp.lang.python (news)
Cross-posted to: calc-reform (list, Swarthmore Math Forum)
Web anchor: http://www.inetarena.com/~pdx4d/ocn/precalc.html
The newest Python (2.0 in beta) has some useful constructs for
those of you using CLI for teaching precalc/calc.[1]
For example, zip() will compose (domain,range) pairs from separate
lists [x1,x2..] [f(x1), f(x2)..]...
>>> dom = [-3,-2,-1,0,1,2,3]
>>> rng = [x*x for x in dom] # see note below
>>> rng
[9, 4, 1, 0, 1, 4, 9]
>>> func = zip(dom,rng)
>>> func
[(-3, 9), (-2, 4), (-1, 1), (0, 0), (1, 1), (2, 4), (3, 9)]
Note: this [f(x) for x in list] "list comprehension" construct
is also new with 2.0.
Of course [-3,-2,-1,0,1,2,3] could be generated using the built-in
range function:
>>> dom = range(-3,3,1)
Be careful not to use key term 'range' as your output list name,
as you'll obscure the built-in range() with your variable and
get an error message next time you try the built-in. Like this:
>>> range = [x*x for x in dom]
>>> range
[9, 4, 1, 0, 1, 4, 9]
>>> range(-10,10,1)
Traceback (innermost last):
File "<pyshell#27>", line 1, in ?
range(-10,10,1)
TypeError: call of non-function (type list)
Uh oh. Now you've gotta go:
>>> del range
to erase your variable and get the built-in back.
Given range() only works with integers, my precalc.py module
uses a longer mkdomain() function. See source code.[2]
In precalc classes, one obvious use of these functions is to
build a discrete math analog of the derivative using definite
epsilon. Let's call this function wiggle() in that we're
"wiggling" a variable x to compute [f(x+epsilon)-f(x)]/epsilon
Here's wiggle():
def wiggle(function,input,epsilon=1e-10):
"""
Accepts a function, value and returns delta f / delta x
for small epsilon (default of 1^-10 may be overridden)
"""
return (function(input+epsilon) - function(input))/epsilon
Let's go to trig and run wiggle on the sine function, for a
domain -pi <= x <= pi.
>>> from precalc import *
>>> dom = mkdomain(-math.pi,math.pi,0.1) # note step by 0.1
>>> rng = [wiggle(math.sin,x) for x in dom]
>>> func = zip(dom,rng)
>>> sine = zip(dom,[math.sin(x) for x in dom]) # sine function
So func now contains wiggled-sine values, which we can graph and
compare with the graph of cosine x.
Lets graph the sine and func (domain,range) pairs. My graphit()
function is a "connect the dots" type, i.e. assume continuity
and fills in spaces between vertices. This gives us the smooth
curves students are used to seeing in text books.
>>> import povray
>>> drawfile = povray.Povray("wiggle1.pov",cf=15,cx=0,cy=0) # [3]
>>> graphit(func,drawfile) # accepts list of [(dom,rng)] pairs
>>> drawfile.cylcolor = "Red"
>>> drawfile.sphcolor = "Red"
>>> graphit(sine,drawfile)
>>> drawfile.close()
The output graph is of both the original sine wave, and the wiggle
function (a discrete math analog of the derivative). See
See Graph 1 at: http://www.inetarena.com/~pdx4d/ocn/precalc.html
Let's do one more example: f(x) = sin(x^2) x:-pi<=x<=pi
>>> def G(x): return math.sin(x**2) # ** = Python's exponentiator
>>> funcG = zip(dom,[G(x) for x in dom])
>>> wiggleG = zip(dom,[wiggle(G,x) for x in dom])
>>> drawfile = povray.Povray("wiggle2.pov",cf=35,cx=0,cy=0)
>>> graphit(wiggleG,drawfile) # accepts list of [(dom,rng)] pairs
>>> drawfile.cylcolor = "Red"
>>> drawfile.sphcolor = "Red"
>>> graphit(funcG,drawfile)
>>> drawfile.close()
See Graph 2.
If you've learned to differentiate composite functions, you know
that the derivative of f(g(x)) = f'(g(x))*g'(x). In this case,
that'd be 2*cos(x**2)*x. Lets plot this function and compare
with wiggleG above:
>>> def derivG(x): return 2*math.cos(x**2)*x
>>> derivfuncG = zip(dom,[derivG(x) for x in dom])
>>> drawfile = povray.Povray("wiggle3.pov",cf=35,cx=0,cy=0)
>>> graphit(derivfuncG,drawfile) # accepts list of [(dom,rng)] pairs
>>> drawfile.close()
See Graph 3.
Clearly this looks like the same function. Note that this
roller coaster function provides a good opportunity to discuss
local minima and maxima, to show how the derivative crosses
the x axis whenever slope = 0, is positive when original
function is rising, negative when falling, and so forth.
In sum, using the compact syntax of Python 2.0, you can make use of
the CLI to facilitate comprehension of the derivative concept. With
some tweaking of the above code, your functions could become
multi-variable, setting the stage for multivariable calculus later
on.
Kirby Urner
Curriculum writer
Oregon Curriculum Network
http://www.inetarena.com/~pdx4d/ocn/
[1] 2.0b is a free download from here:
http://www.pythonlabs.com/tech/python2.0/index.html
CLI = "command line interface"
[2] http://www.inetarena.com/~pdx4d/ocn/python/precalc.html
For code minus extraneous HTML tags:
http://www.inetarena.com/~pdx4d/ocn/python/precalc.py
Also see catenary.html (& .py), which uses much of the
same functionality.
[3] parameters and source for these additional graphing
functions are described in my 'Numeracy + Computer
Literacy' series starting at
http://www.inetarena.com/~pdx4d/ocn/numeracy0.html
You also need Povray at www.povray.org
Many other solutions for creating graphs with Python
have been developed, so don't feel overly tied to my
Povray approach
--------------------------------------------------------------
Cool Math Site of the Week:
'Synergetics on the Web' via
http://west.camel.math.ca/Kabol/
--------------------------------------------------------------