CやJavaで書かれた数値計算アルゴリズムの移植

CやJavaで書かれた数値計算アルゴリズムをBASICに移植するのは,たいていの場合,さほど困難ではありません。
そのためには,JavaやCで書かれたプログラムの読み方を知っておくことが必要です。以下にその要点を示します。

C Java Full BASIC 意味または補足
double x,y; double x,y; DECLARE NUMERIC x,y倍精度実数型の変数宣言
int a,b; int a,b; DECLARE NUMERIC a,b整数型の変数宣言
static int a; static int a;SHARE NUMERIC a静的変数。Full BASICではモジュール本体に書く
extern int a; public static int a;PUBLIC NUMERIC a静的変数。Full BASICではモジュール本体に書く
#define N 1000 final int N=1000;LET N=1000定数宣言。Full BASICでは変数で代用
printf("%g",a); System.out.print(a);PRINT a; Cの%で始まる文字列は書式指定
printf("%g\n",a);System.out.println(a);PRINT a Cの書式文字の\nは改行を意味する
printf("a=%g\n",a);System.out.println("a="+a);PRINT "a=";aJavaで文字列と数値の和は文字列連結を意味する
scanf("%lf",&x);String d1=in.readline();
x=Double.parseDouble(d1);
INPUT x倍精度実数型変数xへの入力
scanf("%d",&a); String d2=in.readline();
a=Integer.parseInt(d2);
INPUT a整数型変数aへの入力
0xfff8 0xfff8 BVAL("fff8",16) 0x....は16進の定数
a=12; a=12; LET a = 12 C,Javaでは,=は代入を意味する
int a=12; int a=12; DECLARE NUMERIC a
LET a = 12
C,Javaでは,変数宣言と代入文を一度に書くことができる
a+=12; a+=12; LET a = a + 12+=の他に,-=,*=,/=などがある
a++; a++; LET a = a + 1 変数に1を加算
a=b++; a=b++; LET a = b
LET b = b + 1
aにbの値を代入後,bに1を加算
a=++b; a=++b; LET b = b + 1
LET a = b
bに1を加算後,aに代入
a=b=c=12; a=b=c=12; LET a,b,c=12 CやJavaの代入文は代入された結果を値として持つ
a / b a / b a/b または IP(a/b) a,bが整数型のとき,a / b は整数除算の商
a % b a % b REMAINDER(a,b) a,bが整数型のとき,a % b は整数除算の余り
a & 1 a & 1 MOD(a,2) a & 1 は整数aの最下位ビットを意味する
a & b a & b BITAND(a,b) (注1)& はビット演算のAND (補足4参照)
a | b a | b BITOR(a,b) (注1) | はビット演算のOR (補足4参照)
a ^ b a ^ b BITXOR(a,b) (注1) ^ はビット演算のXOR (補足4参照)
~a ~a -1-a ~ はビット反転
a << n a << n a*(2^n)   aをnビット左シフトした数
a >> n a >> n IP(a/(2^n))   aをnビット右シフトした数
floor(x) Math.floor(x)INT(x)  
fmod(x,y) Math.fmod(x,y)REMAINDER(x,y) xをyで割った余り。結果はxと同符号。
sqrt(x) Math.sqrt(x)SQR(x)  
atan(x) Math.atan(x)ATN(x)  
atan2(y,x) Math.atan2(y,x)ANGLE(x,y) atan2とANGLEとでは引数の順番が逆
fabs(x) Math.abs(x) ABS(x)  
pow(x,y) Math.pow(x,y)x^y  
double a[15]; double[] a=new double[15];DIM a(0 TO 14)C,Javaの配列添字は0で始まる
a[n] a[n] a(n) 配列aのn番目の要素
int b[5][4];int[][] b=new int[5][4];DIM b(0 TO 4, 0 TO 3)2次元配列(整数型)
a[m][n] a[m][n] a(m,n) 2次元配列の要素
a==b a==b a = b 相等
a!=b a!=b a <> b 非等
!p !p NOT p否定
p && qp && qp AND qpかつq。pが偽ならqを評価しない
p || qp || qp OR qpまたはq。pが真ならqを評価しない
if(条件){…}else{…}if(条件){…}else{…}IF 条件 THEN

ELSE

END IF
 
a=(条件)?式1:式2;a=(条件)?式1:式2;IF 条件 THEN LET a=式1 ELSE LET a=式2
for(i=0;i<n;i++){…}for(i=0;i<n;i++){…}LET i=0
DO WHILE i<n
 …
 LET i=i+1
LOOP
ループの実行でnの値が変化しなければ,
FOR i=0 TO n-1
 …
NEXT i
でもよい
for(;;){…}for(;;){…}DO
 …
LOOP
 
while(条件){…} while(条件){…} DO WHILE 条件
 …
LOOP
 
while(i--){…} while(i-->0){…} DO WHILE i>0
LET i=i-1
 …
LOOP
Cでは非ゼロが真を意味する
while(--i){…} while(--i>0){…} DO
 LET i=i-1
 IF i=0 THEN EXIT DO
 …
LOOP
 
while(1){…} while(true){…} DO

LOOP
 
do {…} while(条件);do {…} while(条件);DO

LOOP WHILE 条件
 
break; break; EXIT DO または EXIT FORbreakは最も内側のループからの脱出
while(…){
 …
 if(条件)continue;
 …
}
while(…){
 …
 if(条件)continue;
 …
}
DO WHILE …
 …
 IF NOT 条件 THEN
  …
 END IF
LOOP
continueは,NEXT文,LOOP文へのGOTOに相当する。
左の形にならないときはGOTO文を使う。
switch (式){
case 1:
  …
  break;
case 2:
  …
  break;
default:
  …
}
switch (式){
case 1:
  …
  break;
case 2:
  …
  break;
default:
  …
}
SELECT CASE 式
CASE 1
 …
CASE 2
 …
CASE ELSE
 …
END SELECT
2個目以降のcaseラベルおよびdefault:の直前が
break;であればSELECT CASEに書き換えられる。
そうでないときはcaseラベルを越えて先に進む。
その場合は個別に書き換え方を工夫する。
switch (式){
case 1:
  …
  break;
case 2:
  …
}
switch (式){
case 1:
  …
  break;
case 2:
  …
}
SELECT CASE 式
CASE 1
 …
CASE 2
 …
CASE ELSE
END SELECT
Full BASICでは,一致するCASE項目がない場合,
CASE ELSEを省けないことに注意
double abc(double x)
{
 …
 return(式)
 …
 return(式)
}
static double abc(double x)
{
 …
 return(式)
 …
 return(式)
}
EXTERNAL FUNCTION abc(x)

LET abc=式
EXIT FUNCTION

LET abc=式
END FUNCTION
return();は関数値を与え,関数から抜ける
void xyz(int a)
{
 …
}
static void xyz(int a)
{
 …
}
EXTERNAL FUNCTION xyz(a)

END FUNCTION
値を持たない関数も関数定義に書き換えて,
呼出し側はダミーの変数への関数値代入にする。
引数の値が関数内で変更されない場合は,
副プログラムに書き換えてもよい。
void xyz(int a[])
{
 …
}
static void xyz(int[] a)
{
 …
}
EXTERNAL SUB xyz(a())
 …
END SUB
C,Javaで配列引数は,実質,参照渡しになるので,
BASICでは副プログラムにする。
double f(double x[])
{
  …
}
static double f(double[] x)
{
   …
}
EXTERNAL FUNCTION f(x())
  …
END FUNCTION
値を持つ関数の場合は,関数内で
配列値を変えていなければ関数定義にする。


注1. JIS規格外の十進BASIC独自拡張 (Ver. 7.5.4以降)


補足1
CやJavaは識別名の大文字と小文字の違いが意味を持つ。そのため,大文字と小文字の違いを無視すると同じになってしまう識別名が存在する場合は,識別名の変更が必要になる。

補足2
CやJavaでは浮動小数点演算の桁あふれは例外状態を引き起こさない(停止しない)。そのため,Full BASICに移植した場合は,適切な例外状態処理を追加しなければ正常に動作しないことがある。

補足3
Cでは,比較演算,論理演算の結果が真であると1,偽であると0の値を持つ。
逆に,条件として数値式を書くと,非ゼロは真,0は偽と解釈される。

a=(x>1)+(x>2);

は,Full BASICで

LET a=0
IF x>1 THEN LET a=a+1
IF x>2 THEN LET a=a+1

と同等。

C,Javaの&&,||は,Full BASICのAND,ORと同様に短絡評価を行う。それに対して,&,|を完全評価の論理演算の意味で用いることができる。だから,どちらの意味に解釈しても結果に差がでないような場合,たとえば,if ( 0<=x & x<1 ) あるいは if ( 0<=x && x<1 ) は,どちらも,IF 0<=x AND x<1 THEN に翻訳してしまってかまわない。
if (--a || --b) のような条件は書き換えに注意が必要。この場合,aの値が0でないときはbの値を変えてはいけない。もしif (--a | --b) だったら,条件のテストを行う前に,a,bどちらも1ずつ減じておけばよい。

補足4
ビット演算の&,|,^ をFull BASICで実現するのは面倒。たとえば,次のような外部関数定義を用意する。

EXTERNAL FUNCTION bitwiseAND(a,b)
DECLARE NUMERIC aa, bb
DECLARE NUMERIC i,c
LET c=0
FOR i=0 TO 31
   LET aa=MOD(a,2)
   LET a=(a-aa)/2
   LET bb=MOD(b,2)
   LET b=(b-bb)/2
   LET c=c+MIN(aa,bb)*2^i
NEXT i
IF c>=2^31 THEN LET c=c-2^32
LET bitwiseAND=c
END FUNCTION

MIN(aa,bb)の部分は,|のときはMAX(aa,bb)に,^のときはMOD(aa+bb,2)に変える。
ただし,a & 7 はMOD(a,8),a & 0xfff8 は INT(a/8)*8 など,算術演算で代用できる場合も多い。

補足5
Cでstatic変数が関数の内側で宣言されている場合,その変数宣言は関数定義または副プログラムの外に移す。

C Full BASIC
double abc(double a)
{
   static int s;      
   ……
}
MODULE m
PUBLIC FUNCTION abc
SHARE NUMERIC s
LET s=0
EXTERNAL FUNCTION abc(a)
   ……
END FUNCTION
END MODULE


補足6
Full BASICはポインタを扱うことができない。
Cでは変数を参照渡しにする目的でポインタを使う場合があるが,その場合は,副プログラムの変数引数を使えばよい。

C Full BASIC 
double a,b;
swap(&a,&b);
CALL SWAP(a,b)&aは変数aのアドレス
void swap(double *x, double *y)
{ double t=*x;
 *x=*y;
 *y=t;
}
EXTERNAL SUB SWAP(x,y)
 LET t=x
 LET x=y
 LET x=y
END SUB
double *x は,double型へのポインタxの宣言
*xはxが参照するdouble型の変数

値を持つ関数がポインタ型の引数も持つ場合は厄介。ただし,値を受け取るだけならそのまま関数でよい。
値を返すために使っている場合は,静的な変数で代用できるなら,モジュールのSHARE変数にして引数から外す。
動的に確保しなければならない変数だったら,値を返すための引数を追加して副プログラムに変える。

Cでは関数へのポインタを扱うこともできるが,そのようなプログラムをFull BASICに移植するのは難しい(汎用の関数にはできない)。

補足7
Full BASICには手続きの再帰呼び出し以外には動的に変数を確保する手段がない。動的に変数を確保する必要がある場合は,配列で代用する。
また,Full BASICにはCの構造体に対応する概念がない。構造体がでてきたら,細かく分けて書き換える。


戻る