Различия между версиями 5 и 7 (по 2 версиям)
Версия 5 от 2018-11-28 02:59:40
Размер: 7777
Редактор: FrBrGeorge
Комментарий:
Версия 7 от 2018-11-28 12:50:02
Размер: 10475
Редактор: FrBrGeorge
Комментарий:
Удаления помечены так. Добавления помечены так.
Строка 57: Строка 57:
В следующих примерах окно `python3` не надо закрывать, иначе придётся заново импортировать `math`, `turtle` и определять функции `drawgraph()` и `scale()`

Ну, или положить код в файл :)
Строка 113: Строка 116:
  * Таким образом, в ''исходном'' графике функции `f(x)` x-коорднаты меняются в заданном интервале, а x-координаты — в пределах области значений функции `f(x)` на этом интервале
  * '''TODO'''
  * Вычисление масштаба и смещения по 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])

}}}
  * '''Замечание''': надо было сначала переместиться на нулевую точку графика в режиме `penup()`
  * Использование конструкции `range(len(graphX))` наводит на мысль, что так можно было не делать. Действительно, можно было воспользоваться [[py3doc:functions.html#zip]]:
   {{{#!highlight pycon
for x,y in zip(graphX, graphY):
    goto(x,y)
    }}}
 * '''TODO'''
 * Работа с `eval()`

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

Разбор Д/З

Про графики

Базовая статья: 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)
          14 
        
    • Всё готово. Нам нужно нарисовать на экране, координаты которого меняются от 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])
           5 
        
    • Замечание: надо было сначала переместиться на нулевую точку графика в режиме penup()

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

      •    1 for x,y  in zip(graphX, graphY):
           2     goto(x,y)
           3 
        
  • TODO

  • Работа с eval()

Д/З

  1. Внезапно — ничего из учебника, TODO про масштабирование и графики-ломаные — где?

    • Про черепашку
  2. TODO

  3. Ввести отрезок, количество точек и ширину экрана, вывести абсциссы точек на экране
  4. Ввести отрезок, количество точек, а также строку — функцию от x (например, x*sin(x**2)), вывести координаты исходных точек графика

  5. Ввести отрезок, количество точек, ширину и высоту экрана, а также строку — функцию от x (например, x*sin(x**2)), вывести координаты точек графика на экране

  6. Нарисовать всё это черепашкой
    • Нарисовать оси координат
    • Что делать, если оси координат лежат в стороне от графика, а рисовать их надо?

Python/PsyPython2018/12_FunctionGraph (последним исправлял пользователь FrBrGeorge 2018-11-29 17:38:32)