【Django】二次関数表示アプリを作成(計算して、Matplotlibでグラフ表示)[Python]

  • URLをコピーしました!
目次

Django

前回、二次関数表示アプリを作成するための準備を行いました。

今回は二次関数を計算して、グラフ化する部分のプログラムを構築していきます。

プログラムを書いていくのは、/webapp/quadraticfunction/views.pyです。

最初にプログラム全体を見せてしまうとこんな感じです。

from django.shortcuts import render
from django.http import HttpResponse
from .forms import QFForm
import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot as plt
import sys
sys.path.append('../')
from webapp import definitions

def plotting(a, b, c, xmax, xmin, ymax, ymin):

    xlist = range(xmin, xmax+1)

    ylist = []
    for i in xlist:
        ylist.append(a * i * i + b * i + c)

    str_a = checksign(a); str_b = checksign(b); str_c = checksign(c)

    if a == 0:
        if b == 0:
            eq = f'y={str_c[0]}'
        elif b != 0:
            eq = f'y={str_b[1]}x{str_c[2]}'
    elif a != 0:
        if b == 0:
            eq = f'y={str_a[1]}x2{str_c[2]}'
        elif b != 0:
            eq = f'y={str_a[1]}x2{str_b[3]}x{str_c[2]}'

    fig = plt.figure()
    plt.clf()

    plt.plot(xlist, ylist)
    plt.grid()
    plt.title(eq,{'fontsize':25})
    plt.xlabel("X", {'fontsize':15})
    plt.ylabel("Y", {'fontsize':15})
    plt.xlim(xmin, xmax)
    plt.ylim(ymin, ymax)

    plt.savefig("./quadraticfunction/static/quadraticfunction/quadraticfunction.png")

def checksign(val):
    if val == 0:
        return '0','','',''
    elif val == 1:
        return '1','','+1','+'
    elif val == -1:
        return '-1','-','-1',"-"
    elif val > 0:
        return f'{val}',f'{val}',f'+{val}',f'+{val}'
    elif val < 0:
        return f'{val}',f'{val}',f'{val}',f'{val}'

def index(request):
    params = definitions.readjson()

    initial_val = {
        'a':1,
        'b':0,
        'c':0,
        'xmin':-10,
        'xmax':10,
        'ymin':-10,
        "ymax":10,
    }

    params['forms']= QFForm(request.POST or None, initial=initial_val)

    plotting(initial_val['a'], initial_val['b'],initial_val['c'], initial_val['xmax'], initial_val['xmin'], initial_val['ymax'], initial_val['ymin'])

    if (request.method == 'POST'):
        a = int(request.POST['a'])
        b = int(request.POST['b'])
        c = int(request.POST['c'])
        xmax = int(request.POST['xmax'])
        xmin = int(request.POST['xmin'])
        ymax = int(request.POST['ymax'])
        ymin = int(request.POST['ymin'])

        params['forms'] = QFForm(request.POST)

        plotting(a, b, c, xmax, xmin, ymax, ymin)

    return render(request, 'quadraticfunction/index.html', params)

plotting関数

今回の修正点で重要なのは一次関数表示アプリの際に作成したplotting関数です。

ここを二次関数用に修正していきます。

まずはplotting関数の引数に「c」を追加します。

def plotting(a, b, c, xmax, xmin, ymax, ymin):

次に計算を行なっている部分。

    xlist = range(xmin, xmax+1)

    ylist = []
    for i in xlist:
        ylist.append(a * i * i + b * i + c)

xの最大値、最小値から、x値のリスト(xlist)を作り、それをfor文で一つずつ取り出し、計算し、ylistに格納します。

「a * i * i + b * i + c」が \(y=ax^2+bx+c\) の計算を行なっている部分です。

次に式を表示する際の場合わけの部分です。

今回は前回とは違う形で場合わけを行っています。

その部分のプログラムを説明する前に新しい関数「checksign」を解説する必要があるので、先に解説します。

checksign関数はこんな感じです。

def checksign(val):
    if val == 0:
        return '0','','',''
    elif val == 1:
        return '1','','+1','+'
    elif val == -1:
        return '-1','-','-1',"-"
    elif val > 0:
        return f'{val}',f'{val}',f'+{val}',f'+{val}'
    elif val < 0:
        return f'{val}',f'{val}',f'{val}',f'{val}'

何をやっているかというと、まず引数として数字「val」を入力します。

valが0、1、−1、0より大きい、0より小さい時で場合わけし、式の表示で使用する形に変換しています。

まとめてみるとこんな感じです。

val出力[0]出力[1]出力[2]出力[3]
0‘0’
1‘1’‘+1’‘+’
-1‘-1’‘-‘‘-1’‘-‘
>0f'{val}’f'{val}’f’+{val}’f’+{val}’
<0f'{val}’f'{val}’f'{val}’f'{val}’
符号+なし
-あり
+なし
-あり
+あり
-あり
+あり
-あり
0ありなしなしなし
1ありなしありなし

f{‘変数名’}という書き方はこちらの記事で解説していますので、良かったらご覧ください。

何故このような関数を作ったかというと、例えばxの前、つまりa、bの係数の「1」は省略しなければいけないけども、cに「1」が来た時は表示しなければいけない。

また数字の符号によって足し算なのか引き算なのかを変化させる、つまり \(y=2x+2)\ のcの位置の「2」には「+」が必要だけど、bの位置の「2」には「+」は必要ない。

こういう複雑な「0」「1」「+」「-」に対応できるように関数を作ったというわけです。

リスト形式で返ってくるので、どの形式を使いたいかインデックスで指定して使います。

この「checksign関数」を使って、式を作成するための部分はこのようにしました。

    str_a = checksign(a); str_b = checksign(b); str_c = checksign(c)

    if a == 0:
        if b == 0:
            eq = f'y={str_c[0]}'
        elif b != 0:
            eq = f'y={str_b[1]}x{str_c[2]}'
    elif a != 0:
        if b == 0:
            eq = f'y={str_a[1]}x2{str_c[2]}'
        elif b != 0:
            eq = f'y={str_a[1]}x2{str_b[3]}x{str_c[2]}'

ここで重要なのは「a」、「b」、「c」がそれぞれ「0」になる場合で式の形式が異なるため、場合わけする必要があるということです。

これで表示するための式は完成しました。

plotting関数の残りの部分はmatplotlibでグラフを作成する部分で、前回から変更はないので解説は割愛します。

    fig = plt.figure()
    plt.clf()

    plt.plot(xlist, ylist)
    plt.grid()
    plt.title(eq,{'fontsize':25})
    plt.xlabel("X", {'fontsize':15})
    plt.ylabel("Y", {'fontsize':15})
    plt.xlim(xmin, xmax)
    plt.ylim(ymin, ymax)

    plt.savefig("./quadraticfunction/static/quadraticfunction/quadraticfunction.png")

index関数

次にindex関数の部分を修正していきます。

一つ目の変更点はplotting関数の引数に「c」が追加されているため、plotting関数を使用している2カ所を修正します。

まずは初期値を使ってプロットする部分。

plotting(initial_val['a'], initial_val['b'],initial_val['c'], initial_val['xmax'], initial_val['xmin'], initial_val['ymax'], initial_val['ymin'])

次に入力された値を使ってプロットする部分(if (request.method == ‘POST’):の後)。

plotting(a, b, c, xmax, xmin, ymax, ymin)

また入力された値を取得する部分に「c」の値を取得するプログラムがないので追加します。

    if (request.method == 'POST'):
        a = int(request.POST['a'])
        b = int(request.POST['b'])
        c = int(request.POST['c'])
        xmax = int(request.POST['xmax'])
        xmin = int(request.POST['xmin'])
        ymax = int(request.POST['ymax'])
        ymin = int(request.POST['ymin'])

これでサーバーを起動し、ブラウザでアクセスし、適当な数字を入れてみました。

二次関数が表示されました。

いろいろ試してみたのですが、グラフも式も大きな問題はなさそうです。

ただまだまだ残念な点もあります。

一つ目として式の中の \(x^2\) の二乗が上付きになっていません。

二つ目として二次関数の重要な点として、頂点がありますが、その値が表示されていないことです。

次回はこれらを修正していきたいと思っていたのですが、少し他のバグが出ていたので、その修正を行います。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次