前回も書いたとおり、配列は関数(サブルーチン)に”実体”として 受け渡されるので、 関数(サブルーチン)中で値を変更すれば、その結果が元のプログラムにも 反映される。 これを利用して、”その3”で作った行列のプログラムを void型関数(サブルーチン)で書き換えてみる。 program 18はprogram 7よりずいぶん長くなってしまって、”なんだこりゃ”と 思うかもしれないけど、program 18で用意した関数(サブルーチン)を そのまま使うことによって、program 19がずいぶんと簡単に書けてしまったこと に注目してください。
|
/* 行列とベクトルの掛け算
program 7を書き換える。掛け算部分と
行列への入力や出力をvoid型関数にする。
また、行列の大きさはdefineで指定する
*/
#include<stdio.h>
#define NN 2 行列・ベクトルの大きさを指定
void m_times_v(double [][],double [],double[]); 五つの関数のプロトタイプ宣言
void m_input(double [][]);
void v_input(double []);
void m_output(double [][]);
void v_output(double []);
main()
{
double a[NN][NN],x[NN],y[NN];
int i,j;
/* キーボード(またはファイル)から行列に値を読み込む */
m_input(a);
/* ベクトルに値を読み込む */
v_input(x);
/* y = ax を計算*/
m_times_v(a,x,y);
/* 出力 */
printf("matrix a:\n");
m_output(a);
printf("vector x:\n");
v_output(x);
printf("vector y=ax:\n");
v_output(y);
} mainはここまで
/* ベクトルw = 行列m * ベクトルv を計算する関数*/
void m_times_v(double m[][NN],double v[],double w[])
{
int i,j;
/* ベクトルwを初期化(値を0に) */
for( i=0; i<NN; ++i){
w[i]=0;
}
/* m*vによりwを求める */
for( i=0; i<NN; ++i){
for( j=0; j<NN; ++j){
w[i] += m[i][j]*v[j];
}
}
}
/* ベクトル(一次元配列)の値をキーボード(またはファイル)から読み込む関数 */
void v_input(double v[])
{
int i;
for( i=0; i<NN; ++i){
scanf("%lf",&v[i]);
}
}
/* 行列(二次元配列)の値をキーボード(またはファイル)から読み込む関数 */
void m_input(double m[][NN])
{
int i,j;
for( i=0; i<NN; ++i){
for( j=0; j<NN; ++j){
scanf("%lf",&m[i][j]);
}
}
}
/* ベクトル(一次元配列)の値を出力する関数 */
void v_output(double v[])
{
int i;
for( i=0; i<NN; ++i){
printf(" %f\n",v[i]);
}
}
/* 行列(二次元配列)の値を出力する関数 */
void m_output(double m[][NN])
{
int i,j;
for( i=0; i<NN; ++i){
for( j=0; j<NN; ++j){
printf(" %f",m[i][j]);
}
printf("\n");
}
}
/* 行列同士の掛け算
program 8を書き換える。
新しく作る関数は掛け算部分だけ。
行列への入力や出力はprogram 18で作った関数を使う。
program 18からm_inputとm_outputをコピーして、このプログラムの
最後につけてください
*/
#include<stdio.h>
#define NN 2 行列の大きさを指定
void m_times_m(double [][],double [][],double[][]); 三つの関数のプロトタイプ宣言
void m_input(double [][]);
void m_output(double [][]);
main()
{
double a[NN][NN],b[NN][NN],c[NN][NN];
/* キーボード(またはファイル)から行列に値を読み込む */
m_input(a);
m_input(b);
/* c = ab を計算*/
m_times_m(a,b,c);
/* 出力 */
printf("matrix a:\n");
m_output(a);
printf("matrix b:\n");
m_output(b);
printf("matrix c=ab:\n");
m_output(c);
} mainはここまで
/* 行列m3 = 行列m1 * 行列m2 を計算する関数*/
void m_times_m(double m1[][NN],double m2[][NN],double m3[][NN])
{
int i,j,k;
/* 行列m3を初期化(値を0に) */
for( i=0; i<NN; ++i){
for( j=0; j<NN; ++j){
m3[i][j]=0;
}
}
/* m1*m2によりm3を求める */
for( i=0; i<NN; ++i){
for( j=0; j<NN; ++j){
for( k=0; k<NN; ++k){
m3[i][j] += m1[i][k]*m2[k][j];
}
}
}
}
C 行列とベクトルの掛け算
program main
parameter(NN=2) 配列の大きさをparameterで指定
real*8 a(NN,NN),x(NN),y(NN)
C 行列に値をいれる(値自身は意味ないです)
call m_input(a,NN)
C ベクトルに値をいれる
call v_input(x,NN)
C y=a*xを計算
call m_times_v(a,x,y,NN)
C 出力
write(*,*)"matrix a:"
call m_output(a,NN)
write(*,*)"vector x:"
call v_output(x,NN)
write(*,*)"vector y=ax:"
call v_output(y,NN)
end mainはここまで
C ベクトルw = 行列m * ベクトルv を計算するサブルーチン
subroutine m_times_v(m,v,w,n)
real*8 m(n,n),v(n),w(n)
C ベクトルwを初期化(値を0に)
do i=1,n
w(i)=0
enddo
C m*vによりwを求める
do i=1,n
do j=1,n
w(i)=w(i)+m(i,j)*v(j)
enddo
enddo
end
C ベクトル(一次元配列)の値をキーボード(またはファイル)
C から読み込むサブルーチン
subroutine v_input(v,n)
real*8 v(n)
read(*,*)(v(i),i=1,n)
end
C 行列(二次元配列)の値をキーボード(またはファイル)
C から読み込むサブルーチン
subroutine m_input(m,n)
real*8 m(n,n)
do i=1,n
read(*,*)(m(i,j),j=1,n)
enddo
end
C ベクトル(一次元配列)の値を出力するサブルーチン
subroutine v_output(v,n)
real*8 v(n)
write(*,*)(v(i),i=1,n)
end
C 行列(二次元配列)の値を出力するサブルーチン
subroutine m_output(m,n)
real*8 m(n,n)
do i=1,n
write(*,*)(m(i,j),j=1,n)
enddo
end
C 行列同士の掛け算
C program 8を書き換える。
C 新しく作るサブルーチンは掛け算部分だけ。
C 行列への入力や出力はprogram 18で作ったサブルーチンを使う。
C program 18からm_inputとm_outputをコピーして、このプログラムの
C 最後につけてください
program main
parameter(NN=2)
real*8 a(NN,NN),b(NN,NN),c(NN,NN)
C 行列に値をいれる
call m_input(a,NN)
call m_input(b,NN)
C c=a*bを計算
call m_times_m(a,b,c,NN)
C 出力
write(*,*)"matrix a:"
call m_output(a,NN)
write(*,*)"matrix b:"
call m_output(b,NN)
write(*,*)"matrix c=a*b:"
call m_output(c,NN)
end mainはここまで
C 行列m3 = 行列m1 * 行列m2 を計算するサブルーチン
subroutine m_times_m(m1,m2,m3,n)
real*8 m1(n,n),m2(n,n),m3(n,n)
C m3を初期化(値を0に)
do i=1,n
do j=1,n
m3(i,j)=0
enddo
enddo
C m1*m2によりm3を求める
do i=1,n
do j=1,n
do k=1,n
m3(i,j)=m3(i,j)+m1(i,k)*m2(k,j)
enddo
enddo
enddo
end