How to see the derivative
Let’s start by reviewing math terms and a few python options. In python, we will be using the turtle as well as the math function module. From the turtle you will need:
shape (), color (), speed (), radians () – general configuration functions
xcor (), ycor () – functions reporting position
goto () – to move the turtle to a point
setheading () – to change the direction of the turtle’s head
done () – function for freezing the screen (needed when working in a sober editor like VSCode. If you write in IDLE, it is not needed)
Also, note that the turtle’s margin is in pixels. If she runs along a parabola, she will run away instantly over the edge of the sheet. So we will introduce some unit UNIT = 100 pixels, for example, well, this is all we will normalize in our units.
From the math module, we take the atan () function – the arctangent. It returns the radian measure of the angle, not the degrees. Then we either take the number pi there – the constant of the math module, quietly divide by it, then multiplying by 180, or we repeat what the “radian measure of the angle” means, or rather, we pass it. Your students, most likely, have not heard about radians.
And the “derivative” in this case is the “tangent of the angle of inclination of the tangent”, that’s what we need. Very similar to the office, “stringing genitives” – “deputy head of the quality control department of the packaging workshop (and others)”. We will disassemble this construction from the end:
we have a graph of the function y = f (x)
there is a point on it, (a, f (a))
if a turtle has come there, if it (the turtle) is running according to the schedule, it needs to look at this point … tangentially to the graph, so we need the equation of this tangent. If the latter is written as y = kx + b, then this k is precisely the derivative: k = f ‘(a)
the function of redirecting the turtle’s head is able to corners, not to straight lines. To say “look in the direction of this straight line” we must convey not a straight line, but “the angle between the straight line along which one should look and the ray Ox”. And if k in the paragraph above is the tangent of that angle, then we need the arctangent of k: atan (f ‘(a))
We get something like this for a parabola:
from turtle import Turtle, done
from math import atan
UNIT = 100
alice = Turtle()
alice.color('green')
alice.shape('turtle')
alice.speed(1)
alice.radians()
for step in range(2 * UNIT):
x = alice.xcor() + 1
y = x**2 / UNIT
alice.goto(int(x), int(y))
k = 2*x / UNIT
alpha = atan(k)
alice.setheading(alpha)
done()
I already did something similar with several +/- high school students. Overall not bad: it can be read and the code works (check it out for yourself). What is the problem here:
it is not entirely clear where we are dividing by unit here, how these places are chosen
what will we have to do with the units when we change the graph
can the whole picture be shifted from the point (0, 0)?
how to transplant it into browser with javascript and styles?
In the browser, we can create a picture using three divs: an outer one with clipped corners and eyes (these are two nested divs). The eyes are displaced somewhere, they must be redirected along the course. You can move using javascript:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
background: gray;
}
.beast {
position: absolute;
background: green;
width: 20px;
height: 20px;
border-radius: 50%;
}
.eye {
background: white;
width: 5px;
height: 5px;
border-radius: 2px;
transform: translateY(5px);
}
</style>
</head>
<body>
<div class="beast">
<div class="eye"></div>
<div class="eye"></div>
</div>
<script>
const UNIT = 100
const beast = document.getElementsByClassName('beast')[0]
let x = 0
let y = 0
let k = 0
let alpha = 0
let id = setInterval(
function() {
x++
y = x * x / UNIT
beast.style.left = x + 'px'
beast.style.top = y + 'px'
k = 2 * x / UNIT
alpha = Math.atan(k) * 180 / Math.PI + 180
beast.style.transform = 'rotate(' + alpha + 'deg)'
if (x > 2 * UNIT) clearInterval(id)
}, 50
)
</script>
</body>
</html>
From this point on, I want to split the code into files. Actually, I also want the Python code, and we divided it: a file with the main logic + a drawing file + a calculator file. In the browser, respectively, plus two more files: markup and styles.
A bonus will be the ability to pass inheritance on the same material. Or even already interfaces. You write an interface to implement a function and a derivative. The rendering functionality uses the interface. And your classes with different calculators calculate different functions.
An example with inheritance, approximately in this form, passed with an eighth-grader at the beginning of the school year (the guy is the son of a programmer, and has been fond of programming for a long time). We have a main file with the main logic, a drawing and a folder with different calculators: basic and inheriting for different functions.
main.py
from painter import Painter
from calculators.calculatorSquare import CalculatorSquare
painter = Painter()
calculator = CalculatorSquare()
for x in range(200):
calculator.nextStep()
y = calculator.getY()
alpha = calculator.getAngleInRadians()
painter.showState(x, y, alpha)
painter.freeze()
painter.py
class Painter:
def __init__(self):
from turtle import Turtle, Screen
self.__beast = Turtle()
self.__beast.shape('turtle')
self.__beast.speed(10)
self.__beast.radians()
def showState(self, x, y, alpha):
self.__beast.goto(x,y)
self.__beast.setheading(alpha)
def freeze(self):
from turtle import done
done()
and a folder calculators with files calculator.py
from math import atan
class Calculator:
def __init__(self):
self._UNIT = 100
self._x = 0
self._y = 0
self._alpha = 0
def nextStep(self):
self._x += 1
def getY(self) -> float:
pass
def getDerivative(self) -> float:
pass
def getAngleInRadians(self) -> float:
return atan(self.getDerivative())
and calculatorSquare.py
from .calculator import Calculator
class CalculatorSquare(Calculator):
def getY(self):
return self._x ** 2 / self._UNIT
def getDerivative(self):
return self._x * 2 / self._UNIT