944BASICの部屋の押し入れ
1番
2002.3.31更新
 
インフォーメーション
■自己紹介の部屋
■944BASICの部屋
■MI-E1ザウルスの部屋
■PI系ザウルスの部屋
■MI-10ザウルスの部屋
■リンクの部屋
944BASICの部屋で古くなったものを収納する押入れです。
目 次
三角関数計算に必須のアークタンジェント 2002.3.3
2D加工の友 Ver 1.0 2002.3.3
入力を考える3 押された文字の編集(改) 2002.3.2
アスキーコード表 2002.2.11
いよいよVAL関数も作ろう 2002.2.8
入力を考える4 数字入力部の作成 2002.2.8
入力を考える2 押された文字の表示 2002.2.8

◆三角関数計算に必須のアークタンジェント (2002.3.3)
ダウンロード:trscatn0.lzh

 以前に紹介したアークタンジェント(atn)は、不完全でした。計算できる範囲が -1<x<1の範囲しかありませんでした。そこで、修正版を作りました。すいません。

 修正版・・・
 944BASICには現在のところ三角関数(sin cos tan)と平方根(sqr)しか数値関数といえるものがサポートされていません。これでは三角関数を逆に解けないので、逆三角関数の基本であるアークタンジェント(atn)関数を944BASICで作ってみました。

 どうやって作るのかというと、テイラー展開という方法を用います。詳しい説明は省きますが、下のプログラムがアークタンジェントのテイラー展開プログラムです。テイラー展開を行うと、アークタンジェントが連続する足し算に展開されます。そして、足される項がどんどん小さくなっていきます。そこで、限りなく小さく(ABS(ATNS)<0.0001)なったときに、計算を終了するようにしています。
 計算結果は、ATNYに入っています。単位はラディアンです。

 ここで、x=1 のときには、atn(x)=π/4, x=-1のときには、atn(x)=-π/4になります。そこで、計算せずにif文で判断し、π/4を代入しています。(π=3.14592653...)

 また、x>1やx<-1のときは、実は、xが-1<x<1の範囲になるように逆数(1/x)を求めて、atn(1/x)を計算しています。それは、下記のような関係が成り立つことを利用しています。

 x>0のとき、atn(x)=π/2-atn(1/x)
 x<0のとき、atn(x)=atn(-1/x)-π/2

 これで、全てのxについて、-π/2 < atn(x) < π/2の範囲で答えを計算することができるようになりました。

REM *******************************
REM *         ATN( ATNX )         *
REM *         戻り値 ATNY         *
REM *******************************
*ATN
atnf=0
if atnx=1 then atny=0.785398:return
if atnx=-1 then atny=-0.785398:return
if atnx>1 then atnx=1/atnx:atnf=1
if atnx<-1 then atnx=-1/atnx:atnf=-1
ATNY=ATNX:ATNT=ATNX:ATNN=3
*ATNLOOP
  ATNT=-ATNT*ATNX*ATNX
  ATNS=ATNT/ATNN
  IF ABS(ATNS)<0.0001 THEN else goto *Atn00
    if atnf=1 then atny=1.570796-atny
    if atnf=-1 then atny=atny-1.570796
    RETURN
*atn00
  ATNY=ATNY+ATNS
  ATNN=ATNN+2
GOTO *ATNLOOP

 アークタンジェントを求めることができると、アークサインやアークコサインもアークタンジェントから求めることができます。以下に式だけ書いておきます。

アークサイン  ASN(X)=ATN(X/SQR(-X*X+1))    0≦X≦1
アークコサイン ACS(X)=π/2-ATN(X/SQR(-X*X+1))  0≦X≦1


◆2D加工の友 Ver 1.0 2002.3.3

ダウンロード:trsc2dk1.lzh

 2D加工の友とは、金型加工やその他加工機を使う環境において、加工数値を計算するときに便利に使えるツールを目指しています。

 このプログラムは、単純に三角形の角度と3辺のうち、どれか2つを入力すると、残りの答えを計算してくれるプログラムです。944BASICでは、こんなプログラムも簡単に組めてしまいます。ブラボー!

 多少の計算誤差は勘弁してください。ゴメン・・・

 

◆入力を考える3 押された文字の編集(改) 2002.3.2

ダウンロード:trscte00.LZH
 ごめんなさい。バグがありましたぁ。m(_ _)m
 数字ボタンには右図のように数字ボタン以外にも編集キーがついています。(数字ボタンを大きくしました(^^;)これらを使って、入力文字を編集する必要があります。そこで、そのルーチンを作ります。数字ボタンで得たキーコードをNv()という配列に編集しつつ代入します。

 まず、数字なので、以下の4つのルールを決めました。

 ・-符号は、一番先頭か、またはEの真後ろにくる。
 ・Eは2個存在しない。
 ・小数点は2個存在しない。
 ・小数点はEの以降に存在しない。

 ここで、「小数点は2個存在しない」と「小数点はEの以降に存在しない」は、小数点ボタンが押されたときに、「既に小数点かまたはEが入力されていれば小数点は打てない」という条件に置き換えても同じです。
 これらを守りつつ各編集キーの動作もプログラムしました。

REM *******************************
REM *     数字配列Nvの編集        *
REM *   引数Ncode, 返り値Nv()     *
REM *******************************
REM DIM Nv(20) 文字数は0〜19の20文字までです
REM NvN 編集エリアサイズ1〜20の範囲
*EDITNV
REM '範囲外(255)'か'入力(13)'だったら、何もせずに戻る
13は'入力'なので編集の終了を意味することになります。255はボタンが正常に押されなかったことを意味します。どちらも、編集する必要が無いので、直ぐReturnです。
 IF (NCODE=255)+(NCODE=13) THEN RETURN
REM 'クリア(12)'だったら、Nv(0)からNv(20)を全てクリアする
クリアなのでNv配列を0に戻します。
 IF NCODE=12 THEN ELSE GOTO *EDITNV00
  FOR EDITNI=0 TO 20
    NV(EDITNI)=0
  NEXT
  RETURN
*EDITNV00
REM '後退(8)'だったら、次に文字の入る場所(先頭から始めてのNv()=0となる場所)を探して
REM それより1つ前の場所を0と置く。
REM forループを途中で抜ける処理が面倒なので、先の処理が終った後も、Nv()=0を
REM 見つけたら1つ前を0にする処理を続けている(^^;
 IF NCODE=8 THEN ELSE GOTO *EDITNV01
先頭で後退ボタンが押されても無視してReturnします
  IF NV(0)=0 THEN RETURN
後は、0の1つ前を0にします。
  FOR EDITNI=0 TO NVN
    IF NV(EDITNI)=0 THEN NV(EDITNI-1)=0
  NEXT
  RETURN
*EDITNV01
REM 次に文字の入る場所(先頭から始めてのNv()=0となる場所)を探す
REM EditNkがその場所
REM NvNまで、全部文字が入っていたら、何もせずに戻る
 EDITNK=NVN
順番にサーチします(INSTR関数なんかも作ったほうがいいかな?)
 FOR EDITNI=0 TO NVN-1
   IF NV(EDITNI)=0 THEN EDITNK=EDITNI:EDITNI=NVN-1
 NEXT
全部埋っていたらReturnする
 IF EDITNK=NVN THEN RETURN
REM 文字が'マイナス(45)'で、文字の入る場所が先頭かEの真後ろだったら入れる
 IF NCODE=45 THEN ELSE GOTO *EDITNV02
EDITNK=0は先頭を意味し、NV(EDITNK-1)は1つ前の文字コードをさします。
  IF EDITNK=0 THEN NV(EDITNK)=NCODE:RETURN
  IF NV(EDITNK-1)=69 THEN NV(EDITNK)=NCODE:RETURN
 ここが↑間違っていました。m(_ _)m
  RETURN
*EDITNV02
REM 文字が'E(69)'のとき、文字列を探して、Eが既に入力されて無いなら入力
IF NCODE=69 THEN ELSE GOTO *EDITNV03
  EDITNC=0
Eのコードをサーチしています
  FOR EDITNI=0 TO EDITNK-1
    IF NV(EDITNI)=69 THEN EDITNC=1:EDITNI=EDITNK-1
  NEXT
EがなかったらNcodeである69を代入
  IF EDITNC=0 THEN NV(EDITNK)=NCODE
  RETURN
*EDITNV03
REM 文字が'小数点(46)'のとき、文字列を探して'小数点'または'E'が既に入力されて無いなら入力。
IF NCODE=46 THEN ELSE GOTO *EDITNV04
  EDITNC=0
小数点のコードとEのコードを探します。
  FOR EDITNI=0 TO EDITNK-1
    IF (NV(EDITNI)=46)+(NV(EDITNI)=69) THEN EDITNC=1:EDITNI=EDITNK-1
  NEXT
小数点かEがなかったらNcodeである46を代入
  IF EDITNC=0 THEN NV(EDITNK)=NCODE
  RETURN
*EDITNV04
4つのルールを満足しているときには、押されたボタンの文字コードを代入します。
REM 普通に押された文字を入力
 NV(EDITNK)=NCODE
 RETURN

 ・数字のルールを考えて、なんとか作れました。

◆アスキーコード表 2002.2.11

 BASICでプログラムを作るときに、キー入力等でアスキーコードを使うことがあります。そこで、アスキーコード表を記載しました。

 普段のアスキーコード表は16進数で書かれていることが多いので、一般的な16進コードバージョンを用意しました(上表)。また、944BASICでは、16進数表記がサポートされていないので、10進数表記も作ってみました(下表)。

 表の見方は、16進表記の場合、横列が8ビットの上位4ビットで、縦が下位4ビットを表します。例えば、Aのアスキーコードは&H41となります。10進表記の場合は、横列が10の位で、縦が1の位を表します。例えば、Aのアスキーコードは65となります。10進表示の方がプログラムを作るときには参考になるかと思います。

 表の中の黄色の表記は、ザウルスMI-E1のキー入力で返ってくるキーコードです。本当はもっと多くのキーコードが返って来るのですが、この表では0〜127までのコードだけを載せています。
 実際にキーボードの英数をたたいても、小文字のコードや数字のコードは返ってはきません。
 
 
アスキーコード表(16進数)
   上位
下位
0
1
2
3
4
5
6
7
0
   
スペース
0
@
P
`
p
1
   
!
1
A
Q
a
q
2
   
"
2
B
R
b
r
3
中断
 
#
3
C
S
c
s
4
   
$
4
D
T
d
t
5
   
%
5
E
U
e
u
6
   
&
6
F
V
f
v
7
   
'
7
G
W
g
w
8
後退
 
(
8
H
X
h
x
9
タブ
 
)
9
I
Y
i
y
A
LF
 
*
:
J
Z
j
z
B
HOME
ESC
+
;
K
[
k
{
C
クリア
,
<
L
\
l
|
D
改行
-
=
M
]
m
}
E
 
.
>
N
^
n
~
F
 
/
?
O
_
o
削除
(注:→←↑↓は、カーソルキー)
(注:黄色はMI-E1で得ることができるキーコード、ただし&H7F以下の)
 
アスキーコード表(10進数)
 
0
1
2
3
4
5
6
7
8
9
10
11
12
0
 
LF
 
(
2
<
F
P
Z
d
n
x
1
 
HOME
 
)
3
=
G
Q
[
e
o
y
2
 
クリア
 
スペース
*
4
>
H
R
\
f
p
z
3
中断
改行
 
!
+
5
?
I
S
]
g
q
{
4
     
"
,
6
@
J
T
^
h
r
|
5
     
#
-
7
A
K
U
_
i
s
}
6
     
$
.
8
B
L
V
`
j
t
~
7
   
ESC
%
/
9
C
M
W
a
k
u
削除
8
後退
 
&
0
:
D
N
X
b
l
v
 
9
タブ
 
'
1
;
E
O
Y
c
m
w
 
 (注:→←↑↓は、カーソルキー)
(注:黄色はMI-E1で得ることができるキーコード、ただし127以下の)


◆いよいよVAL関数も作ろう 2002.2.8
ダウンロード:trscte00.LZH

 前に書いたVAL関数がバグっていました。すいません。今回は詳細に説明いたしまする。m(_ _)m忝い

 数値計算を行うためには、入力された文字を数値に置きかえる必要があります。BASICでINPUT文を使って変数に直接数値を代入できますが、944BASICでは、まだINPUT文がサポートされていません。そこで、自分でINPUT文も作る必要があるのですが、こうなると、直接数字を代入することが難しいので、数字を文字として読み込んでから数値に直すという手順を踏まなければなりません。
 
 文字を数字に変換する関数はBASICではVALに当たります。バリアブル関数っていうやつですね。これを作ります。

 Nv(20)という配列に数字を文字コードとして入力します。例えば、100なら、
Nv(0)=49
Nv(1)=48
Nv(2)=48
Nv(3)=0
と入ります。
 この状態でサブルーチン *VALを呼び出すと、VALVに100という値が代入されます。このVALでは×10の何乗というようなE表記も使えます。例えば、1.253E8というような文字コードをVALN配列に入れても、VALVに計算値を代入します。ただし、16進数の10進数変換などはサポート外です。
 

REM *******************************
REM *        VALルーチン          *
REM *    引数 Nv()配列          *
REM *        戻り値 VALV          *
REM *      (Nv配列は不定に)       *
REM *******************************
REM DIM Nv(20)
*VAL
REM 長さチェック
数値コード列の長さを調べます。
FOR VALI=0 TO 20
  IF NV(VALI)=0 THEN VALA=VALI:VALI=20
NEXT
ValAに長さがはいります
REM 符号のチェック
VALS=0
IF NV(0)=45 THEN VALS=1
負なら、ValSに1がはいります
REM 負の数だったら、符号分前にずらす
IF VALS=1 THEN ELSE GOTO *VAL04
  FOR VALI=1 TO VALA
    NV(VALI-1)=NV(VALI)
  NEXT
  VALA=VALA-1
REM ↑はい、正の数になりました
*VAL04
REM NvがNullだったら0を返す。そしてRetuenする。
IF VALA=0 THEN VALV=0:RETURN

REM ↓いきなりEだったら、頭に1を付けます小文字のeも見てます。
IF (NV(0)=69)+(NV(0)=101) THEN ELSE GOTO *VAL05
先ず後にずらして、
  FOR VALI=1 TO VALA
    NV(VALA-VALI+1)=NV(VALA-VALI)
  NEXT
1(49)を代入します。
  NV(0)=49
長さと終了部(Null)をずらします。
  VALA=VALA+1
  NV(VALA)=0
*VAL05
REM ↓いきなり小数点だったら、頭に0を付けます
IF NV(0)=46 THEN ELSE GOTO *VAL02
先ず後にずらして、
  FOR VALI=1 TO VALA
    NV(VALA-VALI+1)=NV(VALA-VALI)
  NEXT
0(48)を代入します。
  NV(0)=48
長さをずらします。
  VALA=VALA+1
*VAL02
REM Eが使われているかどうかチェックします小文字もチェック
VALE=-1
FOR VALI=0 TO VALA-1
  IF (NV(VALI)=69)+(NV(VALI)=101) THEN NV(VALI)=0:VALE=VALI:VALI=VALA-1
NEXT
Eがあったら、Eまでの部分を数値変換します。そのためにEの部分までを文字長さにします。
IF VALE<>-1 THEN VALA=VALE
REM Eがあったら、EのところをNullにしました。んで、文字数(ValA)もそれに合わしました。
REM そして、ValEにEの位置がスタックされました。
REM 小数点の有無を調べます
VALK=-1
FOR VALI=0 TO VALA-1
  IF NV(VALI)=46 THEN VALK=VALI:VALI=VALA
NEXT
REM 小数点を調べ終わりました
REM 小数点の位置が(ValA-1)だったら、小数点を消しましょう
小数点の位置が一番最後だったら、小数点はいらないので消す。
IF VALK=VALA-1 THEN NV(VALK)=0:VALK=-1:VALA=VALA-1
ここから数値化処理開始です
VALV=0
REM 小数点がなかったら、普通に計算、最後に符号を付ける
IF VALK=-1 THEN ELSE GOTO *VAL01
  FOR VALI=0 TO VALA-1
    POWX=10:POWY=VALA-1-VALI:GOSUB *POW
    VALV=VALV+(NV(VALI)-48)*POWA
  NEXT
符号を付けています
  IF VALS=1 THEN VALV=-VALV
  GOTO *VAL03 次はE以降の計算へ
*VAL01
REM 小数点がありました
小数部の数値化
FOR VALJ=VALK+1 TO VALA-1
  POWX=0.1:POWY=VALJ-VALK:GOSUB *POW
  VALV=VALV+(NV(VALJ)-48)*POWA
NEXT
整数部の数値化
FOR VALJ=0 TO VALK-1
  POWX=10:POWY=VALK-VALJ-1:GOSUB *POW
  VALV=VALV+(NV(VALJ)-48)*POWA
NEXT
符号を付けています
IF VALS=1 THEN VALV=-VALV
*VAL03
E以降の計算をします
Eが無ければReturnします
IF VALE=-1 THEN RETURN
E以前の数値をValXに保存します
VALX=VALV
E以降の文字をNv配列の先頭から入れ直します。
FOR VALI=0 TO 20
  NV(VALI)=NV(VALE+VALI+1)
  IF NV(VALI)=0 THEN VALI=20
NEXT
そして、VALをもう一度読んでE以降を数値化します。
GOSUB *VAL
E以降分の計算をします
POWX=10:POWY=VALV:GOSUB *POW
そして、もともとの数値に掛けて、できあがり。
VALV=VALX*POWA
RETURN

 ・ふう〜、疲れた。


◆入力を考える4 数字入力部の作成 2002.2.8

ダウンロード:trscte00.LZH

 入力を考える1,2,3で作った各サブルーチンと以前作ったVALルーチンを用いて数字の入力部を作ります。
 こっこでお詫びねm(_ _)m前に書いたValルーチンには思いっきりバグがありました。ごめんなさいm(_ _)m。上で書き直します。

REM *******************************
REM *       数字入力ルーチン      *
REM *    引数 NumInX,NumInY,NvN   *
REM *    戻り値 ValV              *
REM *******************************
REM 入力している数値が表示されるところのX,Y座標=(NumInX,NumInY)
REM 入力範囲(エリア)のサイズ NvN
*NUMINPUT
初期化です。
LOCATE NUMINX,NUMINY
FOR NUMINPI=0 TO NVN
  NV(NUMINPI)=0
  PRINT ' ';
NEXT
とりあえず先頭にアンダーバーカーソルを出す
LOCATE NUMINX,NUMINY:PRINT '_'
*NUMINPUT00 SYNC
ここから'改行(13)'コードが押されるまで1文字ずつ入力します
GOSUB *INPUTNUMKEY
IF NCODE=13 THEN GOTO *NUMINPUT01
  GOSUB *EDITNV
  LOCATE NUMINX,NUMINY:GOSUB *NVPRINT
  GOTO *NUMINPUT00
*NUMINPUT01
Nv()に入った文字コードを数値に変換します。
GOSUB *VAL
RETURN

 ・これで完成。
 

◆入力を考える2 押された文字の表示 2002.2.8
ダウンロード:trscte00.LZH
 数字ボタンを表示して、押されたボタンの文字コードを返すところを前に書きました。こんどは、そのコードを文字として画面に表示するところを作ってみたいと重います。

 944BASICは文字変数の結合等の処理がほとんどサポートされていないので、数字を文字ではなくて、文字コードという数値として扱うほうが楽です。そこでそのようにします。

 文字コードを文字として画面に表示するためには、NvChar()のような配列を作って、それコードをと置換していくことにしました。表示すべき文字コードは配列Nv()に順番に代入されています。

REM *******************************
REM *       文字配列の表示        *
REM *******************************
REM Nv(20)に代入された数字(アスキーコード)を文字として表示する
REM DIM Nv(20)
REM DIM NvChar(12)='-','.','E','0','1','2','3','4','5','6','7','8','9'
REM NvN:表示文字エリアサイズ(Max文字個数:0〜19の20文字までです)
REM locateで指定された位置に書きます
*NVPRINT
 配列0から1つずつ順番に数字(文字)に変換していきます。ただし、0はスペース、69はEに置き換えます。他は文字コードから45を引けばNvChar配列と合うようになってます。
 FOR NVI=0 TO NVN-1
  IF NV(NVI)=0 THEN PRINT ' ';
  IF NV(NVI)=69 THEN PRINT 'E';
  IF (NV(NVI)>=45)*(NV(NVI)<=57) THEN PRINT NVCHAR(NV(NVI)-45);
*NVPR00
 NEXT
RETURN

 ・数だけの表示は、簡単ですね。