|
 |
|
2014/10/6(Mon) 17:19:38|NO.65457
連立方程式を解くプログラムを作っています。
Cで書いていましたがandroid化できると聞いたのでHSPに移植しようと思いました。
このプログラムを実行すると
0で除算しました というエラーが出てしまいます。
本やネットで調べましたが解決策がよくわかりません。
長文すいません。
x1=0:y1=0 ; 画面左上の座標
x2=320:y2=480 ; 画面右下の座標
screen 0,x2,y2 ;ウィンドウ表示
cls 4;画面を黒で塗る
dim a;~24 変数の初期化
dim b
dim c
dim d
dim e
dim f
dim g
dim h
dim i
dim j
dim k
dim l
dim m
dim x
dim y
dim z
dim p
dim q
dim n
color 255,0,0 :font "MS ゴシック",80,1;~27 下の括弧の表示
pos 180,330
mes"{"
color 255,0,0 :font "MS ゴシック",15,1;~30 上の式の表示
pos 100,130
mes" X+ Y= "
pos 75,130;~34 上の式のaの取得
objsize 30,15
a=""
input a
pos 135,130;~38 上の式のbの取得
objsize 30,15
b=""
input b
pos 190,130;~42 上の式のcの取得
objsize 30,15
c=""
input c
color 255,0,0 :font "MS ゴシック",15,1;~45 下の式の表示
pos 100,180
mes" X+ Y= "
pos 75,180;~49 上の式のaの取得
objsize 30,15
d=""
input d
pos 135,180;~53 上の式のbの取得
objsize 30,15
e=""
input e
pos 190,180;~57 上の式のcの取得
objsize 30,15
f=""
input f
pos 230,225;~60 OKボタンの表示
objsize 80,30
button"OK",*main
stop
*main
l = a
h = b
m = c
if a<d : goto *ax :else:goto *vs;上の式と下の式の大きさを合わせるときに大きさを変える式の判断
*ax;~73 下の式が大きかったときの計算
g =d/a
a*=g
b*=g
c*=g
goto *cv
*vs;~79 上の式が大きかったときの計算
g =a/d
d =g*d
e =g*e;
f =g*f;
goto *cv
*cv
j =b-e;~84 上の式から下の式を引く計算
k =c-f
y = k/j;yを求める計算
x = (-h*y+m)/l;xを求める計算
mes"X="+x;xの表示
mes"Y="+y;yの表示

| |
|
2014/10/6(Mon) 18:04:11|NO.65458
ん~...。
なんか色々おかしいですが、応急処置をするとざっとこんな感じでしょうか?
アルゴリズムのチェックまではしていませんが、
A = matrix([1,2],[4,5])
Ax = matrix([3],[6])
(※Maxima風の記述ですみません。表現しやすいので。)
でちゃんと正しい解を出してくれることだけは一応確認しました。
x1=0:y1=0 ; 画面左上の座標
x2=320:y2=480 ; 画面右下の座標
screen 0,x2,y2 ;ウィンドウ表示
cls 4;画面を黒で塗る
a = 0.0
b = 0.0
c = 0.0
d = 0.0
e = 0.0
f = 0.0
g = 0.0
h = 0.0
i = 0.0
j = 0.0
k = 0.0
l = 0.0
m = 0.0
x = 0.0
y = 0.0
z = 0.0
p = 0.0
q = 0.0
n = 0.0
color 255,0,0 :font "MS ゴシック",80,1;~27 下の括弧の表示
pos 180,330
mes"{"
color 255,0,0 :font "MS ゴシック",15,1;~30 上の式の表示
pos 100,130
mes" X+ Y= "
pos 75,130;~34 上の式のaの取得
objsize 30,15
input a
pos 135,130;~38 上の式のbの取得
objsize 30,15
input b
pos 190,130;~42 上の式のcの取得
objsize 30,15
input c
color 255,0,0 :font "MS ゴシック",15,1;~45 下の式の表示
pos 100,180
mes" X+ Y= "
pos 75,180;~49 上の式のaの取得
objsize 30,15
input d
pos 135,180;~53 上の式のbの取得
objsize 30,15
input e
pos 190,180;~57 上の式のcの取得
objsize 30,15
input f
pos 230,225;~60 OKボタンの表示
objsize 80,30
button"OK",*main
stop
*main
l = a
h = b
m = c
if a<d : goto *ax :else:goto *vs;上の式と下の式の大きさを合わせるときに大きさを変える式の判断
*ax;~73 下の式が大きかったときの計算
g =d/a
a*=g
b*=g
c*=g
goto *cv
*vs;~79 上の式が大きかったときの計算
g =a/d
d =g*d
e =g*e;
f =g*f;
goto *cv
*cv
j =b-e;~84 上の式から下の式を引く計算
k =c-f
y = k/j;yを求める計算
x = (-h*y+m)/l;xを求める計算
mes"X="+x;xの表示
mes"Y="+y;yの表示
2元連立一次方程式ですか...。
ちょいと行列の話になりますが、
A = matrix([a11,a12],[a21,a22])
x = matrix([x1],[x2])
Ax = matrix([0],[0])
と言う風に行列のアイデアを使えば、aとかbとかまどろっこしい変数を使わなくても
配列で楽に扱えます。
n元連立1次方程式まで解いてくれるようなのをつくると面白いですね。
解の存在のチェックをしてくれたり、解空間まで求めてくれると需要あるかも?

| |
|
2014/10/6(Mon) 18:07:20|NO.65459
提示されたスクリプトでうまく動かない理由のヒントをいくつか挙げます。
① 計算用の変数 (a,b,...)が文字列型で初期化されていた。
② /とすべきを/と書いている箇所がある。
③ -とすべきを-としている箇所がある。
①を直すために、実数型に置き換えておきました。
|
|
2014/10/6(Mon) 19:02:57|NO.65461
#define ctype f(%1) strf("%%g",%1)
//0.02500・・・を0.025にする
x1=3.0
x2=2.0
y1=4.0
y2=1.0
a1=5.0
a2=0.0
x5=x1:y5=y1:a5=a1
cls 4
color 255,0,0
font "",50
pos 20,50
mes "{"
color 255,0,0
font "",25
pos 50,50
mes ""+f(x1)+"x+"+f(y1)+"y="+f(a1)
mes ""+f(x2)+"x+"+f(y2)+"y="+f(a2)
p1=x1*x2
p2=p1/x1
p3=p1/x2
x1=p2*x1
y1=p2*y1
a1=p2*a1
x2=p3*x2
y2=p3*y2
a2=p3*a2
//上、下の式のx同士の最小公倍数を掛ける
color 255,0,0
font "",50
pos 20,120
mes "{"
font "",25
pos 50,120
mes ""+f(x1)+"x+"+f(y1)+"y="+f(a1)
mes ""+f(x2)+"x+"+f(y2)+"y="+f(a2)
x3=x1-x2
y3=y1-y2
a3=a1-a2
//上の式から下の式を引く
boxf 20,170,200,171
mes " "+f(y3)+"y="+f(a3)
y=a3/y3
//約分
mes " y="+f(y)
//yもとめられた
ky=y*y5
//xを求めるために、yを代入
pos 50,250
mes ""+f(x5)+"x+"+f(ky)+"="+f(a5)
a5=a5+ky*-1
//移項
ky=""
mes ""+f(x5)+"x="+f(a5)
x=a5/x5
//約分
mes "x="+f(x)
//xもとめられた
pos 50,350
mes "x="+f(x)+" y="+f(y)
boxf 20,375,200,376
|
|
2014/10/7(Tue) 00:16:33|NO.65467
一次の方程式を解くなら線形代数が最も簡単だと思います。
ax + by = p
cx + dy = q
について A = [a b ; c d] , B = [p ; q] すると
AX = B が成り立つので X = (A^-1)B となります。
(A^-1) = (1 / detA) * t[Aの余因子行列]
ですが、t[Aの余因子行列]は(2,2)型の正方行列の公式から[d -b ; -c a]となるので、
[d -b ; -c a] * [p ; q]を計算すると解[x ; y]がでます。
3元や4元の方程式を解きたい場合はまじめに余因子行列と転置行列を計算して
逆行列を求めた後、具体的な方法は知りませんが行列を高速に計算するアルゴリズムで
積を計算してやれば同じように解がでるはずです。
/*
AX = P を X = (A^-1)P に変形して考えます。
このコードでは二元1次方程式のみ解けます。
A^-1 = (1 / detA) * t[Aの余因子行列]
を使えば何元でも解けるはずです。
*/
// 変数初期化
x1 = 3 : y1 = 2 : a1 = 1
x2 = 7 : y2 = 5 : a2 = -1
ix1 = 0 : iy1 = 0
ix2 = 0 : iy2 = 0
Ax = 0 : Ay = 0
objsize 24, 20
// 式1
pos 16, 8 : input x1 : pos 48, 12 : mes "X +"
pos 80, 8 : input y1 : pos 112, 12 : mes "Y ="
pos 144, 8: input a1
// 式2
pos 16, 32 : input x2 : pos 48, 36 : mes "X +"
pos 80, 32 : input y2 : pos 112, 36 : mes "Y ="
pos 144, 32: input a2
objsize 80, 24 : button "計算", *label
stop
*label
color 255, 255, 255 : boxf 0, 64, 640, 480 : color
// 係数行列についてdet(行列式の値)を求める
detA = double( x1 * y2 - x2 * y1 )
pos 8, 96 : mes "detA = " +detA + "\n"
if detA == 0.0 : dialog "解無し、もしくは全て" : stop
// 係数行列の逆行列の各要素を求める
idetA = 1.0 / double(detA)
ix1 = double(y2) * idetA
iy1 = double(-y1) * idetA
ix2 = double(-x2) * idetA
iy2 = double(x1) * idetA
// 逆行列を表示
mes "係数行列の逆行列 = [" + ix1 + " " + iy1 + " ; " + ix2 + " " + iy2 + " ]\n"
// 係数行列の逆行列と[ a1 a2 ]の積を求める ( [2,1]型 )
Ax = double(ix1) * double(a1) + double(iy1) * double(a2)
Ay = double(ix2) * double(a1) + double(iy2) * double(a2)
// 表示
mes "X = " + Ax
mes "Y = " + Ay
stop

| |
|
2014/10/7(Tue) 19:04:03|NO.65470
皆さん本当にありがとうございます。
僕はまだ学生ですが、たくさん練習してもっとすごいプログラムを書けるようになりたいです。
たくさんのアドバイスありがとうございました。
|
|