第26講 n進数の演算---その2 減法
第7話 プログラム解説その1
プログラム主要部分再掲
int hk(int*a,int*b,int* c,int n,int g,int u){
int i,j,k,d[10000],e[10000],h;
for(i=0;i<=g+1;i++){
c[i]=0;
d[i]=0;
e[i]=0;
}
if(u>0){
h=1;
for(i=0;i<g;i++){
d[i]=a[i];
if(b[i]==n)h=0;
if(h==1)e[i]=b[i];
}
}
else{
h=1;
for(i=0;i<g;i++){
d[i]=b[i];
if(a[i]==n)h=0;
if(h==1)e[i]=a[i];
}
}
for(i=0;i<=g;i++){
if(d[i]>=e[i]){
c[i]=d[i]-e[i];
}
else{
for(j=i+1;j<g;j++){
if(d[j]>0){
d[j]--;
break;
}
else{
d[j]=n-1;
}
}
c[i]=n+d[i]-e[i];
}
}
int ik;
for(i=g-1;i>=0;i--){
if(c[i]>0){
if(u>0){
c[i+1]=n;
ik=i+1;
}
else{
c[i+2]=n;
c[i+1]=n+1;
ik=i+2;
}
break;
}
}
return(ik);
}
解説
引き算実行関数について解説します。
プログラム再掲の中に入っていませんが、
引き算実行関数int hkは、
j3=hk(a,b,d,n,j,u);
によって呼び出されていますが、
int hk(int*a,int*b,int* c,int n,int g,int u)
呼び出し側のdに対応するものは、
呼び出される側では、
int* c であることは、
ここまでついてきた優秀な皆さんにはいう必要のないことですね。
呼び出す側と呼び出される側の引数名は異なっていてよいのでしたね。
int hk(int*a,int*b,int* c,int n,int g,int u)
としてあることによって、
int i,j,k,d[10000],e[10000],h;
名称がmainのd[10000]と重なっていても問題ないわけです。
変数や配列のスコープ=適用範囲は、
関数内に限られています。
mainのdは、cとして引き渡されていますで、
ダブらないわけです。
それならば、はじめから
j3=hk(a,b,c,n,j,u);
で呼び出せばいいじゃないか・・・・
当然の疑問です。
ですが、目標は四則演算です。
つまり、加減乗除(足し算・引き算・かけ算・割り算)です。
それでも、毎回初期化すれば、
mainで配列を増やしていく必要はないでしょう。
毎回初期化をして変数や配列を増やさない・・・
これは、メモリー節約として重要な考え方であり、
一理あることを認めます。
認めつつも、
演算結果を残しておきたいという心情も、
お分かりかとも思います。
for(i=0;i<=g+1;i++){
c[i]=0;
d[i]=0;
e[i]=0;
}
は初期化です。
初期化しておかないと、
配列に適当な値が入っていていろいろと邪魔をする場合があるからです。
私の記憶では、さらに私が知っている範囲の言語では、
変数を宣言すると、
自動的に0に初期化されたと思うのですが、
C言語とC++の場合は、
ポインタも扱うせいか、
相当適当な値
(数学でいう適当は、適切という意味ですが、
ここではいいかげんという意味で使っています。)
がはいっている場合が多いのです。
ですから、変数も配列も必ず0等に初期化する習慣を
是非とも身につけて頂きたいと思います。
0等にというのは、かけ算を扱う場合には、
1に初期化しておいた方がよいなど、
ケースによって違うからです。
if(u>0){
・・・
}
else{
・・・}
}
は、場合分けしています。
uが1ときは、a=bを意味し、
uカが2ときには、a>bを意味していました。
すなわち、a≧bの場合には、
if文の肯定側を、
a≧bが否定されている場合、すなわちa<bの場合には、
if文の否定側が実行されます。
ここでやっていることは、
大きい方(正確に言うと小さくない方)をdに代入して、
小さい方をeに代入しています。
もちろん、for文の範囲
for(i=0;i<g;i++){
を見ればお分かりのように、
終わり記号nの入っている1つ手前までの代入です。
ですから、
a=n356901
b=n12601
だとすれば、
d=00356901
e=00012601
となるわけです。
配列
int i,j,k,d[10000],e[10000],h;
d,eを用意する理由は、足し算のときと同様で、
終わり記号nを排除することです。
表示のときには、有効なツールである終わり記号nは、
演算の場合には邪魔をします。
for(i=0;i<=g+1;i++){
c[i]=0;
d[i]=0;
e[i]=0;
}
は
for(i=0;i<=g;i++){
c[i]=0;
d[i]=0;
e[i]=0;
}
でも、すなわち
a=n356901
b=n12601
d=0356901
e=0012601
で十分でしたね。