[Poke-Pro]PC-G850で方程式ソルバーを作る

# [新企画]Poke-Pro
新企画`Poke-Pro`では、ポケコンで作成したプログラムを投稿していく企画です。シリーズとなります。BASIC言語に軸を置き、気まぐれでC言語にも触れていきます。

## はじめに
こんにちは、bockringです。シリーズ投稿の4本目は、方程式ソルバーを作成します。2次方程式までの対応です。

## 目標と妥協点
まず目標です。以下の点を実装します。
- $bx=d$あるいは$bx+c=d$の形の一次方程式を解く
- $ax^2+bx+c=d$の形の二次方程式を解く
- 虚数解を持つ二次方程式を解く
- 二元一次方程式を解く
- メニュー方式の採用
- 分かりやすく単純な操作の採用

逆に妥協点は、
- 速度(表示の遅さ)

です。これらを踏まえて実装します。

適当に作るプログラムとしてはかなり複雑な、そして同時に高機能なソルバーになると思います。

## 実装
BASICで作成します。手打ちなので間違っているかもしれません。その場合は適宜直していただければと思います。よければコメントでお知らせください、訂正します。

2次方程式までのソルバーですから、解の公式$\frac{-b±\sqrt{b^2-4ac}}{2a}$をそのまま使います。

```basic:SOLVER.TXT
10 CLS :PRINT "  **** Eq.Solver+ ****"
20 PRINT "":PRINT "   =======MODE=======":PRINT "   1:Normal  2:Linear":WAIT 30:K$=""
30 WHILE K$=""
40 K$= INKEY$
50 WEND
60 IF K$="1" OR K$="2" THEN 70 ELSE 30
70 IF K$="1" THEN 1000 ELSE 2000
1000 I=1
1010 CLS :PRINT " *** Solver(Normal) ***":PRINT "":PRINT "ax^2+bx+c=d"
1020 IF I=1 THEN PRINT "Input a":INPUT "[INPUT]",A:GOTO 1060
1030 IF I=2 THEN PRINT "Input b":INPUT "[INPUT]",B:GOTO 1060
1040 IF I=3 THEN PRINT "Input c":INPUT "[INPUT]",C:GOTO 1060
1050 IF I=4 THEN PRINT "Input d":INPUT "[INPUT]",E:GOTO 1060
1060 IF I<=4 THEN I=I+1:GOTO 1010
1070 C=C-E:D=B*B-4*A*C
1080 IF D<0 THEN M=1 ELSE M=0
1090 WHILE M=0
1100 D= SQR (D):X=(-B+D)/(2*A):Y=(-B-D)/(2*A)
1110 CLS :PRINT " *** Solver(Normal) ***":PRINT "":IF X=Y THEN PRINT "x=",X ELSE PRINT "x=",X," ",Y
1120 M=2
1130 WEND
1140 WHILE M=1
1150 D= SQR (-D):D=D/(2*A)
1160 CLS :PRINT " *** Solver(Normal) ***":PRINT "":PRINT "Complex (a+bi,a-bi)":PRINT "a=",(-B)/(2*A):PRINT "b=",D
1170 M=2
1180 WEND
1190 END
2000 I=1
2010 CLS :PRINT " *** Solver(Linear) ***":PRINT ""
2020 PRINT "    1: _a_x+_b_y=_c_":PRINT "    2: _a_x+_b_y=_c_"
2030 IF I=1 THEN PRINT "Input 1a":INPUT "[INPUT]",A:GOTO 2090
2040 IF I=2 THEN PRINT "Input 1b":INPUT "[INPUT]",B:GOTO 2090
2050 IF I=3 THEN PRINT "Input 1c":INPUT "[INPUT]",C:GOTO 2090
2060 IF I=4 THEN PRINT "Input 2a":INPUT "[INPUT]",D:GOTO 2090
2070 IF I=5 THEN PRINT "Input 2b":INPUT "[INPUT]",E:GOTO 2090
2080 IF I=6 THEN PRINT "Input 2c":INPUT "[INPUT]",F:GOTO 2090
2090 IF I<=6 THEN I=I+1:GOTO 2010
2100 X=B:Y=E:A=A*Y:B=B*Y:C=C*Y:D=D*X:E=E*X:F=F*X
2110 IF A=D THEN CLS :PRINT "":PRINT "========================":PRINT " ERROR HAS BEEN OCCURED":PRINT "    TYPE : BAD VALUE":PRINT "========================":PRINT "":END
2120 X=(C-F)/(A-D)
2130 Y=(C-X*A)/B
2140 CLS :PRINT " *** Solver(Linear) ***":PRINT "":PRINT "x=",X,"y=",Y
```

今回のプログラムは、モードごとに行き来したり、一部の処理を1箇所にまとめたりするために、`GOTO`命令を多用しています。そのため、行番号は一部連番にしていません。`1000`行目や`2000`行目などの端数のない数字を使うことで後で見返した時の可読性を向上させています。

また、容量を減らすのは、程々にしています。

今回は画面サイズなども考慮に入れているコードですから、PC-G850シリーズ以外では動作しません。4行表示のポケコンでは以下のコードを使用してください(ただし1行に24文字以上表示できることが条件です)。以下のコードは4行表示のSHARP機ならほぼ確実に動作すると思います。(動作確認はしていないので

またCASIO機で、動作しなかった場合は適宜変更してください。

```basic:SOLVER.TXT
10 CLS :PRINT "  **** Eq.Solver+ ****"
20 PRINT "":PRINT "   =======MODE=======":PRINT "   1:Normal  2:Linear":WAIT 30:K$=""
30 WHILE K$=""
40 K$= INKEY$
50 WEND
60 IF K$="1" OR K$="2" THEN 70 ELSE 30
70 IF K$="1" THEN 1000 ELSE 2000
1000 I=1
1010 CLS :PRINT " *** Solver(Normal) ***":PRINT "ax^2+bx+c=d"
1020 IF I=1 THEN PRINT "Input a":INPUT "[INPUT]",A:GOTO 1060
1030 IF I=2 THEN PRINT "Input b":INPUT "[INPUT]",B:GOTO 1060
1040 IF I=3 THEN PRINT "Input c":INPUT "[INPUT]",C:GOTO 1060
1050 IF I=4 THEN PRINT "Input d":INPUT "[INPUT]",E:GOTO 1060
1060 IF I<=4 THEN I=I+1:GOTO 1010
1070 C=C-E:D=B*B-4*A*C
1080 IF D<0 THEN M=1 ELSE M=0
1090 WHILE M=0
1100 D= SQR (D):X=(-B+D)/(2*A):Y=(-B-D)/(2*A)
1110 CLS :PRINT " *** Solver(Normal) ***":IF X=Y THEN PRINT "x=",X ELSE PRINT "x=",X," ",Y
1120 M=2
1130 WEND
1140 WHILE M=1
1150 D= SQR (-D):D=D/(2*A)
1160 CLS :PRINT " *** Solver(Normal) ***":PRINT "Complex (a+bi,a-bi)":PRINT "a=",(-B)/(2*A):PRINT "b=",D
1170 M=2
1180 WEND
1190 END
2000 I=1
2010 CLS :PRINT " *** Solver(Linear) ***"
2020 PRINT "    1: _a_x+_b_y=_c_":PRINT "    2: _a_x+_b_y=_c_"
2030 IF I=1 THEN PRINT "Input 1a":INPUT "[INPUT]",A:GOTO 2090
2040 IF I=2 THEN PRINT "Input 1b":INPUT "[INPUT]",B:GOTO 2090
2050 IF I=3 THEN PRINT "Input 1c":INPUT "[INPUT]",C:GOTO 2090
2060 IF I=4 THEN PRINT "Input 2a":INPUT "[INPUT]",D:GOTO 2090
2070 IF I=5 THEN PRINT "Input 2b":INPUT "[INPUT]",E:GOTO 2090
2080 IF I=6 THEN PRINT "Input 2c":INPUT "[INPUT]",F:GOTO 2090
2090 IF I<=6 THEN I=I+1:GOTO 2010
2100 X=B:Y=E:A=A*Y:B=B*Y:C=C*Y:D=D*X:E=E*X:F=F*X
2110 X=(C-F)/(A-D)
2120 Y=(C-X*A)/B
2130 CLS :PRINT " *** Solver(Linear) ***":PRINT "x=",X,"y=",Y
```

これで動くかな？CASIO機は持っていないので分かりません。

## 動作画像
![IMG_0417.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777721/1c20cc63-c145-4467-b43c-ce3e5eb8de59.jpeg)
↑`RUN`を入力し実行するとこの画面が表示されます。

![IMG_0418.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777721/7c03a80e-bbbc-4997-9754-8f8b706fe6d6.jpeg)
↑`ax^2+bx+c=d`と式が表示され、a, b, c, dの全変数の値を入力します。

![IMG_0419.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777721/2f87b225-ede4-48ca-bc71-aaef2ca616e7.jpeg)
↑すべての値を入力し、答えが表示されました。$x$の二次方程式$3x^2-7x+5=0$の解は$1.166666667±5.52770E-1$(`=1.166666667±0.552770i`)と分かりました。手計算で解いたほうが速いです、以上。

## 改善点
- 表示速度の遅さ

行ごとに段々と表示されて動作が遅いのですが、何が原因は何でしょうか…

機能面は理想通りですが、レスポンスがイマイチ過ぎるんですよね。

また、操作はCUI感が残ってしまいましたが、それでも起動時の画面をキー押下式メニューにしたり、全体的にもどの入力を求めているのかを分かりやすく示したり、ある程度目標は達成できたと思います。

## おわりに
今回も定番のプログラム、方程式ソルバーを作成しました。

他の言語とは違う文法に少し戸惑いは残っていますが、若干慣れてきたような気がします。

いつかポケコンに微分・積分の機能を実装してみたいです。数値微分・不定積分が解けたらいいと思いますね。

---

シリーズ記事の一覧

https://qiita.com/bockring/private/0cc7d2fbbdad53b25c1b

---