Differences between revisions 18 and 19
Revision 18 as of 2018-11-29 13:58:43
Size: 10945
Editor: FrBrGeorge
Comment:
Revision 19 as of 2018-11-29 14:38:32
Size: 10947
Editor: FrBrGeorge
Comment:
Deletions are marked like this. Additions are marked like this.
Line 180: Line 180:
 1. Нарисовать всё это черепашкой! (в отличие от предыдущей задачи, координат черепашки начинаются не с 0, см. выше)  1. Нарисовать всё это черепашкой! (в отличие от предыдущей задачи, координаты черепашки начинаются не с 0, см. выше)

Построение графика функции

Разбор Д/З

Про графики

Базовая статья: FrBrGeorge/PythonScaleAndRotate

  • Что такое график?
    • Отображение точек x:f(x)
    • ⇒ f(x) должно ∃
    • Ограничения по началу и концу (не бесконечный, а от A до B)

    • Количество точек в графике? Бесконечно много!
      • ⇒ отрезки, а не непрерывная кривая
      • ⇒ ломаная (N точек, N-1 отрезок)
  • Черепашка и график синуса
    • Повторение: циклический конструктор списка:
        [ выражение for имя in последователоьность ]
          или
        [ выражение for имя, имя in последователоьность_пар]
          и т. п.
        Например, [i*2+1 for i in range(6)]
    • Подготовим черепашье поле
         1 >>> from math import *
         2 >>> from turtle import *
         3 >>> reset()
      
    • Точки — это пары координат (x, y)
    • График — это последовательность таких пар, например
         1 >>> graph = [(-200, -119), (-160, -100), (-120, -57), (-80, 0), (-40, 57), (0, 100), (40, 119), (80, 109), (120, 71), (160, 16), (200, -42)]
         2 >>> def drawgraph(gr):
         3   penup() # Сначала перейдём на начало графика
         4   for x,y in gr:
         5     goto(x,y)
         6     pendown()
         7 
         8 >>> drawgraph(graph)
      
    • Попробуем нарисовать график синуса:
         1 >>> reset()
         2 >>> graph = [(i,sin(i)) for i in range(-100,100)]
         3 >>> drawgraph(graph)
      
      • Фигня какая-то: волняшки слишком частые, но слишком невысокие
    • Масштаб по X и Y:
         1 >>> reset()
         2 >>> graph = [(i,sin(i/20)*60) for i in range(-100,100)]
         3 >>> drawgraph(graph)
      
      • Но это уже непонятно чего график. В каких границах?

Попробуем разобраться

В следующих примерах окно 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)

           1 >>> a, b = -6, 3
           2 >>> N=10
           3 >>> X = [a+i*(b-a)/(N-1) for i in range(N)]
           4 >>> X
           5 [-6.0, -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0]
           6 
        

        Соответственно, значения функции f(x) в этих точках (предположим, f — это sin):

           1 >>> from math import *
           2 >>> f=sin
           3 >>> Y = [f(x) for x in X]
           4 >>> Y
           5 [0.27941549819892586, 0.9589242746631385, 0.7568024953079282, -0.1411200080598672, -0.9092974268256817, -0.8414709848078965, 0.0, 0.8414709848078965, 0.9092974268256817, 0.1411200080598672]
           6 
        
  • Функция масштабирования+переноса (да, это аффинные преобразования, только никому не говорите, а то испугаются).
    • (см. статью) Чтобы превратить точку 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

      • prop.png

    • Напишем функцию scale(), которая это вычисляет:

         1 >>> def scale(x, a0, b0, a1, b1):
         2     """превратить точку x из диапазона a0,b0 в точку x1 из диапазона a1,b1"""
         3     return (x-a0)/(b0-a0)*(b1-a1)+a1
         4 
         5 >>> scale(10,-100,100,-10,10)
         6 1.0
         7 
      
    • То есть список из N штук x-координат точек графика можно представить как scale() счётчика i из диапазона 0,N-1 в диапазон a,b:

         1 >>> N=10
         2 >>> a,b = -6, 3
         3 >>> X = [a+i*(b-a)/(N-1) for i in range(N)]
         4 >>> X
         5 [-6.0, -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0]
         6 >>> X = [scale(i, 0, N-1, a, b) for i in range(N)]
         7 >>> X
         8 [-6.0, -5.0, -4.0, -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0]
         9 
      
  • Координаты исходного графика vs координаты на экране
    • Таким образом, в исходном графике функции f(x) x-коорднаты меняются в заданном интервале, а x-координаты — в пределах области значений функции f(x) на этом интервале. Диапазон по x мы задаём, а вот диапазон по y, он же f(x) придётся поискать среди значений функции в точках графика

         1 >>> a, b = -6,3
         2 >>> n = 100
         3 >>> X = [scale(i,0,n-1,a,b) for i in range(n)]
         4 >>> X[0]
         5 -6.0
         6 >>> X[-1]
         7 3.0
         8 >>> f=sin
         9 >>> Y = [f(x) for x in X]
        10 >>> ymin, ymax = min(Y), max(Y)
        11 >>> ymin, ymax
        12 (-0.9996789142433975, 0.9998892390840102)
        13 
      
      • Обратите внимание на то, что диапазон оказался близок, но не равен диапазону «настоящего» синуса (-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.

      • вычислим координаты точек на экране и нарисуем график!
           1 >>> graphX = [scale(x, a, b, Left, Right) for x in X]
           2 >>> graphY = [scale(y, ymin, ymax, Bottom, Top) for y in Y]
           3 >>> for i in range(len(graphX)):
           4 >>>     goto(graphX[i],graphY[i])
        

        roughsin.png

    • Замечание: надо было сначала переместиться на нулевую точку графика в режиме penup()

    • Замечание: Использование конструкции range(len(graphX)) наводит на мысль, что так можно было не делать. Действительно, можно было воспользоваться zip():

      •    1 >>> for x,y  in zip(graphX, graphY):
           2 >>>    goto(x,y)
        
  • Теперь можно рисовать график любой функции! Вводим строку (в которой есть x), а вместо f(x) обрабатываем эту строку eval():

       1 >>> sf = input()
       2 x/(sin(x)+2)
       3 >>> Y = [eval(sf) for x in X]
       4 >>> # вычисляем и строим график заново …
    
    • formula.png

Д/З

В домашнем задании используются приёмы непосредственно из лекции. Фактически, это одна задача, так что не пугайтесь, что она состоит из нескольких пунктов.

  1. Прощёлкать этот конспект, добиться того, чтобы последняя кривая получилась
  2. EJudge: IntervalDots 'Забор и щели'

    Ввести (через запятую) три числа: вещественные A и B — границы отрезка по X, и целое N — количество равноудалённых точек на нём. Вывести (через пробел) положение этих точек (их X-координаты).

    Input:

    -3,4,15
    Output:

    -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
  3. EJudge: IntervalFormula 'Ординаты графика'

    Ввести (через запятую) три числа: вещественные A и B — границы отрезка по X, и целое N — количество равноудалённых точек на нём. Затем ввести строку F, в которой содержится распознаваемая Python3 формула (в ней есть x и, возможно, A, B, N, арифметические операции и/или функции модуля math). Вывести через пробел значение этой формулы на всех точках отрезка (см. предыдущую задачу).

    Input:

    -3,4,15
    x**2
    Output:

    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
  4. EJudge: AlmostGraph 'Почти график'

    Ввести (через запятую) пять чисел:

    • вещественные A и B — границы отрезка по X
    • и целое N — количество равноудалённых точек на нём
    • целые W и H — ширину и высоту экрана

    Затем ввести строку F, в которой содержится распознаваемая Python3 формула (в ней есть x и, возможно, A, B, N, арифметические операции и/или функции модуля math). Вывести через пробел абсциссы, а в следующей строке — ординаты графика на экране (которые изменяются от 0 до W и от 0 до H соответственно).

    Input:

    -3,4,15,350,200
    x**2
    Output:

    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
  5. Нарисовать всё это черепашкой! (в отличие от предыдущей задачи, координаты черепашки начинаются не с 0, см. выше)
    • Дополнительные задания:
    • Нарисовать оси координат
    • Подписать их с помощью turtle.write()

    • Что делать, если оси координат лежат в стороне от графика, а рисовать их надо?

Python/PsyPython2018/12_FunctionGraph (last edited 2018-11-29 14:38:32 by FrBrGeorge)