今度は中央値の計算も実装してみました。
#include <stdio.h> #include <string.h> #include <stdlib.h> // qsortに必要 double mean(double d[],int n) { int i; double sum = 0.0; for( i=0 ; i<n ; i++ ){ sum += d[i]; } return sum/n; } // qsort用の関数.qsortに渡せる形の関数を作成する必要がある. // 仮引数や返り値の形式は指定されていることに注意. int doublecmp(const void *a,const void *b){ return( *(double *)a - *(double *)b ); } double median(double d[],int n) { int i; double dCpy[n]; // コピーを作成するのは元データの順序保持のため // 今回の統計量を計算するだけのコードでは不要ではあるが. for( i=0 ; i<n ; i++ ){ dCpy[i] = d[i]; } qsort(dCpy,n,sizeof(double),doublecmp); if( n % 2 ){// 奇数 return dCpy[n/2]; }else{// 偶数 return (dCpy[n/2] + dCpy[n/2 -1])/2.0; } } double min(double d[],int n) { int i; int idx = 0; // 最小値の添字 for( i=0 ; i<n ; i++ ){ if( d[idx] > d[i] ){ idx = i; } } return d[idx]; } double max(double d[],int n) { int i; int idx = 0; // 最大値の添字 for( i=0 ; i<n ; i++ ){ if( d[idx] < d[i] ){ idx = i; } } return d[idx]; } /* double (*p[])(double [],int)={mean,median,min,max,NULL}; char *cp[]={"mean","median","min","max",NULL}; */ typedef struct funcs{ double (*p)(double [],int);// 関数へのポインタ char *cp;// 入力の文字列と比較する関数を表す文字列へのポインタ }FUNCS; FUNCS f[]={ {mean,"mean"}, {median,"median"}, {min,"min"}, {max,"max"}, {NULL,NULL} };// ここで一元管理.最後のNULLは終端を示す番兵 double (*setfunc(char *str))(double d[],int n) { int i; /* for( i=0 ; cp[i] != NULL ; i++ ){ if( !strcmp(cp[i],str) ){ return p[i]; } } */ for( i=0 ; f[i].cp != NULL ; i++ ){ if( !strcmp(f[i].cp,str) ){ return f[i].p; } } printf("error in setfunc\n"); return NULL; // 入力の文字列が不適切な場合 } int main(void) { double (*f)(double d[],int n); double a[10]={0,1,2,3,4,5,6,7,8,19}; f = setfunc("mean"); printf("%lf\n",f(a,10)); f = setfunc("min"); printf("%lf\n",f(a,10)); f = setfunc("max"); printf("%lf\n",f(a,10)); return 0; }
gccによるコンパイル後の実行結果は、以下の通り。
mean = 5.500000 median = 4.500000 min = 0.000000 max = 19.000000
構造体を用いて管理することによって、関数を表す文字列と関数がまとまり、
対応が分かりやすくなって、バグが出にくくなったのではないかと思う。
ライブラリのqsortを利用しているが、本来は全体をソートする必要はなく、
およそ途中までのソートができていれば良いので、そのあたりは工夫できるかも。