4084
Комментарий:
|
← Версия 19 от 2018-11-29 17:38:32 ⇥
10947
|
Удаления помечены так. | Добавления помечены так. |
Строка 55: | Строка 55: |
'''TODO''' | |
Строка 57: | Строка 56: |
Попробуем разобраться | === Попробуем разобраться === В следующих примерах окно `python3` не надо закрывать, иначе придётся заново импортировать `math`, `turtle` и определять функции `drawgraph()` и `scale()` Ну, или положить код в файл :) |
Строка 59: | Строка 61: |
* Количество замеров * В заборе 10 досок, значит, в нём 9 дыр! * Функция масштабирования+переноса (да, это аффинные преобразования, только никому не говорите, а то испугаются) |
* В заборе 10 досок, значит, в нём 9 щелей! * Количество замеров: график функции `f(x)` на интервале `[a,b]` * — это ломаная, которая начинается в точке `(a,f(a))`, а заканчивается в точке `(b, f(b))`. * Если в ней `N` вершин, то отрезков в ней `N-1`. * Абсциссы вершин находятся на равном расстоянии друг от друга, т. е. на расстоянии `(b-a)/(N-1)` * Допустим, вершин у нас `10`, значит, отрезков `9`; допусти также, что `a=-6`, `b=3` * Расстояние между абсциссами `(3-(-6))/9 == 1` * абсцисса 0-й вершины — начало интервала, `a`, т. е. `-6` * абсцисса 1-й вершины — начало отрезка + первый отрезок, т. е `a+(b-a)/(N-1)`, т. е. `-6+1*1 == -5` * абсцисса 2-й вершины — начало отрезка + первых два отрезка, т. е `a+2*(b-a)/(N-1)`, т. е. `-6+2*1 == -4` * … * абсцисса 8-й (№ N-2) вершины — `a+(N-2)*(b-a)/(N-1)`, т. е. `-6+8*1 == 2` * абсцисса 9-й (№ N-1) вершины — `a+(N-1)*(b-a)/(N-1)`, т. е. `-6+9*1 == 2` (т. е. `b`) {{{#!highlight pycon >>> a, b = -6, 3 >>> N=10 >>> X = [a+i*(b-a)/(N-1) for i in range(N)] >>> X [-6.0, -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0] }}} Соответственно, значения функции `f(x)` в этих точках (предположим, `f` — это `sin`): {{{#!highlight pycon >>> from math import * >>> f=sin >>> Y = [f(x) for x in X] >>> Y [0.27941549819892586, 0.9589242746631385, 0.7568024953079282, -0.1411200080598672, -0.9092974268256817, -0.8414709848078965, 0.0, 0.8414709848078965, 0.9092974268256817, 0.1411200080598672] }}} * Функция масштабирования+переноса (да, это аффинные преобразования, только никому не говорите, а то испугаются). * (см. [[FrBrGeorge/PythonScaleAndRotate|статью]]) Чтобы превратить точку x,,0,, из диапазона a,,0,,,b,,0,, в точку x,,1,, из диапазона a,,1,,,b,,1,,, надо: * составить пропорцию x,,0,, делит отрезок a,,0,,,b,,0,, в той же пропорции, что и x,,1,, делит отрезок a,,1,,,b,,1,, * т. е. (x,,0,,-a,,0,,)/(b,,0,,-a,,0,,) = (x,,1,,-a,,1,,)/(b,,1,,-a,,1,,) * и x,,1,, = (x,,0,,-a,,0,,)/(b,,0,,-a,,0,,)*(b,,1,,-a,,1,,)+a,,1,, {{attachment:prop.png}} * Напишем функцию `scale()`, которая это вычисляет: {{{#!highlight pycon >>> def scale(x, a0, b0, a1, b1): """превратить точку x из диапазона a0,b0 в точку x1 из диапазона a1,b1""" return (x-a0)/(b0-a0)*(b1-a1)+a1 >>> scale(10,-100,100,-10,10) 1.0 }}} * То есть список из N штук x-координат точек графика можно представить как `scale()` счётчика `i` из диапазона 0,N-1 в диапазон a,b: {{{#!highlight pycon >>> N=10 >>> a,b = -6, 3 >>> X = [a+i*(b-a)/(N-1) for i in range(N)] >>> X [-6.0, -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0] >>> X = [scale(i, 0, N-1, a, b) for i in range(N)] >>> X [-6.0, -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0] }}} |
Строка 63: | Строка 116: |
* Вычисление масштаба и смещения по X * Вычисление масштаба и смещения по Y=f(X) * Требуют нахождения max() и min() |
* Таким образом, в ''исходном'' графике функции `f(x)` x-коорднаты меняются в заданном интервале, а x-координаты — в пределах области значений функции `f(x)` на этом интервале. Диапазон по `x` мы задаём, а вот диапазон по `y`, он же `f(x)` придётся поискать среди значений функции в точках графика {{{#!highlight pycon >>> a, b = -6,3 >>> n = 100 >>> X = [scale(i,0,n-1,a,b) for i in range(n)] >>> X[0] -6.0 >>> X[-1] 3.0 >>> f=sin >>> Y = [f(x) for x in X] >>> ymin, ymax = min(Y), max(Y) >>> ymin, ymax (-0.9996789142433975, 0.9998892390840102) }}} Обратите внимание на то, что диапазон оказался близок, но не равен диапазону «настоящего» синуса (-1 … 1; а почему не равен?) * Что касается координат на экране, то они совсем другие. Они зависят от размеров окна (минус размер рамки) {{{#!highlight pycon >>> reset() >>> window_width() 800 >>> window_height() 900 >>> Border = 20 # Отступ от края окна >>> Left, Right = -window_width()/2+Border, window_width()/2-Border >>> Bottom, Top = -window_height()/2+Border, window_height()/2-Border >>> Left, Right, Bottom, Top (-380.0, 380.0, -430.0, 430.0) >>> for x in Left, Right: >>> for y in Bottom, Top: >>> goto(x,y) }}} * Всё готово. Нам нужно нарисовать на экране, координаты которого меняются от `Left` до `Right` по `x` и от `Bottom` до `Top` по `y`, график функции `f(x)` на `n` точках в диапазоне от `a` до `b`, зная, что `f(x)` на этом диапазоне принимает значения от `miny` дол `maxy`. * вычислим координаты точек на экране и нарисуем график! {{{#!highlight pycon >>> graphX = [scale(x, a, b, Left, Right) for x in X] >>> graphY = [scale(y, ymin, ymax, Bottom, Top) for y in Y] >>> for i in range(len(graphX)): >>> goto(graphX[i],graphY[i]) }}} {{attachment:roughsin.png}} * '''Замечание''': надо было сначала переместиться на нулевую точку графика в режиме `penup()` * '''Замечание''': Использование конструкции `range(len(graphX))` наводит на мысль, что так можно было не делать. Действительно, можно было воспользоваться [[py3doc:functions.html#zip|zip()]]: {{{#!highlight pycon >>> for x,y in zip(graphX, graphY): >>> goto(x,y) }}} * Теперь можно рисовать график ''любой'' функции! Вводим строку (в которой есть `x`), а вместо `f(x)` обрабатываем эту строку `eval()`: {{{#!highlight pycon >>> sf = input() x/(sin(x)+2) >>> Y = [eval(sf) for x in X] >>> # вычисляем и строим график заново … }}} {{attachment:formula.png}} |
Строка 67: | Строка 174: |
1.#0 Внезапно — ничего из учебника, '''TODO''' про масштабирование и графики-ломаные — где? * Про черепашку * '''TODO''' 1. Ввести отрезок, количество точек и ширину экрана, вывести абсциссы точек на экране 1. Ввести отрезок, количество точек, а также ''строку'' — функцию от x (например, `x*sin(x**2)`), вывести координаты исходных точек графика 1. Ввести отрезок, количество точек, ширину и высоту экрана, а также ''строку'' — функцию от x (например, `x*sin(x**2)`), вывести координаты точек графика на экране 1. Нарисовать всё это черепашкой |
В домашнем задании используются приёмы непосредственно из лекции. Фактически, это ''одна'' задача, так что не пугайтесь, что она состоит из нескольких пунктов. 1.#0 Прощёлкать этот конспект, добиться того, чтобы последняя кривая получилась 1. <<EJCMC(114, IntervalDots, Забор и щели)>> 1. <<EJCMC(114, IntervalFormula, Ординаты графика)>> 1. <<EJCMC(114, AlmostGraph, Почти график)>> 1. Нарисовать всё это черепашкой! (в отличие от предыдущей задачи, координаты черепашки начинаются не с 0, см. выше) Дополнительные задания: |
Строка 75: | Строка 183: |
* Подписать их с помощью `turtle.write()` |
Построение графика функции
Разбор Д/З
Про графики
Базовая статья: FrBrGeorge/PythonScaleAndRotate
- Что такое график?
- Отображение точек x:f(x)
- ⇒ f(x) должно ∃
Ограничения по началу и концу (не бесконечный, а от A до
- Количество точек в графике? Бесконечно много!
- ⇒ отрезки, а не непрерывная кривая
- ⇒ ломаная (N точек, N-1 отрезок)
- Черепашка и график синуса
- Повторение: циклический конструктор списка:
[ выражение for имя in последователоьность ] или [ выражение for имя, имя in последователоьность_пар] и т. п. Например, [i*2+1 for i in range(6)]
- Подготовим черепашье поле
- Точки — это пары координат (x, y)
- График — это последовательность таких пар, например
- Попробуем нарисовать график синуса:
- Фигня какая-то: волняшки слишком частые, но слишком невысокие
- Масштаб по X и Y:
- Но это уже непонятно чего график. В каких границах?
- Повторение: циклический конструктор списка:
Попробуем разобраться
В следующих примерах окно python3 не надо закрывать, иначе придётся заново импортировать math, turtle и определять функции drawgraph() и scale()
Ну, или положить код в файл
- График как список координат
- В заборе 10 досок, значит, в нём 9 щелей!
Количество замеров: график функции f(x) на интервале [a,b]
— это ломаная, которая начинается в точке (a,f(a)), а заканчивается в точке (b, f(b)).
Если в ней N вершин, то отрезков в ней N-1.
Абсциссы вершин находятся на равном расстоянии друг от друга, т. е. на расстоянии (b-a)/(N-1)
Допустим, вершин у нас 10, значит, отрезков 9; допусти также, что a=-6, b=3
Расстояние между абсциссами (3-(-6))/9 == 1
абсцисса 0-й вершины — начало интервала, a, т. е. -6
абсцисса 1-й вершины — начало отрезка + первый отрезок, т. е a+(b-a)/(N-1), т. е. -6+1*1 == -5
абсцисса 2-й вершины — начало отрезка + первых два отрезка, т. е a+2*(b-a)/(N-1), т. е. -6+2*1 == -4
- …
абсцисса 8-й (№ N-2) вершины — a+(N-2)*(b-a)/(N-1), т. е. -6+8*1 == 2
абсцисса 9-й (№ N-1) вершины — a+(N-1)*(b-a)/(N-1), т. е. -6+9*1 == 2 (т. е. b)
Соответственно, значения функции f(x) в этих точках (предположим, f — это sin):
- Функция масштабирования+переноса (да, это аффинные преобразования, только никому не говорите, а то испугаются).
(см. статью) Чтобы превратить точку x0 из диапазона a0,b0 в точку x1 из диапазона a1,b1, надо:
составить пропорцию x0 делит отрезок a0,b0 в той же пропорции, что и x1 делит отрезок a1,b1
т. е. (x0-a0)/(b0-a0) = (x1-a1)/(b1-a1)
и x1 = (x0-a0)/(b0-a0)*(b1-a1)+a1
Напишем функцию scale(), которая это вычисляет:
То есть список из N штук x-координат точек графика можно представить как scale() счётчика i из диапазона 0,N-1 в диапазон a,b:
- Координаты исходного графика vs координаты на экране
Таким образом, в исходном графике функции f(x) x-коорднаты меняются в заданном интервале, а x-координаты — в пределах области значений функции f(x) на этом интервале. Диапазон по x мы задаём, а вот диапазон по y, он же f(x) придётся поискать среди значений функции в точках графика
- Обратите внимание на то, что диапазон оказался близок, но не равен диапазону «настоящего» синуса (-1 … 1; а почему не равен?)
- Что касается координат на экране, то они совсем другие. Они зависят от размеров окна (минус размер рамки)
1 >>> reset() 2 >>> window_width() 3 800 4 >>> window_height() 5 900 6 >>> Border = 20 # Отступ от края окна 7 >>> Left, Right = -window_width()/2+Border, window_width()/2-Border 8 >>> Bottom, Top = -window_height()/2+Border, window_height()/2-Border 9 >>> Left, Right, Bottom, Top 10 (-380.0, 380.0, -430.0, 430.0) 11 >>> for x in Left, Right: 12 >>> for y in Bottom, Top: 13 >>> goto(x,y)
Всё готово. Нам нужно нарисовать на экране, координаты которого меняются от Left до Right по x и от Bottom до Top по y, график функции f(x) на n точках в диапазоне от a до b, зная, что f(x) на этом диапазоне принимает значения от miny дол maxy.
- вычислим координаты точек на экране и нарисуем график!
- вычислим координаты точек на экране и нарисуем график!
Замечание: надо было сначала переместиться на нулевую точку графика в режиме penup()
Замечание: Использование конструкции range(len(graphX)) наводит на мысль, что так можно было не делать. Действительно, можно было воспользоваться zip():
Теперь можно рисовать график любой функции! Вводим строку (в которой есть x), а вместо f(x) обрабатываем эту строку eval():
Д/З
В домашнем задании используются приёмы непосредственно из лекции. Фактически, это одна задача, так что не пугайтесь, что она состоит из нескольких пунктов.
- Прощёлкать этот конспект, добиться того, чтобы последняя кривая получилась
EJudge: IntervalDots 'Забор и щели'
Ввести (через запятую) три числа: вещественные A и B — границы отрезка по X, и целое N — количество равноудалённых точек на нём. Вывести (через пробел) положение этих точек (их X-координаты).
-3,4,15
-3.0 -2.5 -2.0 -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0
EJudge: IntervalFormula 'Ординаты графика'
Ввести (через запятую) три числа: вещественные A и B — границы отрезка по X, и целое N — количество равноудалённых точек на нём. Затем ввести строку F, в которой содержится распознаваемая Python3 формула (в ней есть x и, возможно, A, B, N, арифметические операции и/или функции модуля math). Вывести через пробел значение этой формулы на всех точках отрезка (см. предыдущую задачу).
-3,4,15 x**2
9.0 6.25 4.0 2.25 1.0 0.25 0.0 0.25 1.0 2.25 4.0 6.25 9.0 12.25 16.0
EJudge: AlmostGraph 'Почти график'
Ввести (через запятую) пять чисел:
- вещественные A и B — границы отрезка по X
- и целое N — количество равноудалённых точек на нём
- целые W и H — ширину и высоту экрана
Затем ввести строку F, в которой содержится распознаваемая Python3 формула (в ней есть x и, возможно, A, B, N, арифметические операции и/или функции модуля math). Вывести через пробел абсциссы, а в следующей строке — ординаты графика на экране (которые изменяются от 0 до W и от 0 до H соответственно).
-3,4,15,350,200 x**2
0.0 25.0 50.0 75.0 100.0 125.0 150.0 175.0 200.0 225.0 250.0 275.0 300.0 325.0 350.0 112.5 78.125 50.0 28.125 12.5 3.125 0.0 3.125 12.5 28.125 50.0 78.125 112.5 153.125 200.0
- Нарисовать всё это черепашкой! (в отличие от предыдущей задачи, координаты черепашки начинаются не с 0, см. выше)
- Дополнительные задания:
- Нарисовать оси координат
Подписать их с помощью turtle.write()
- Что делать, если оси координат лежат в стороне от графика, а рисовать их надо?