这里只实现了因素只有一级的情况。
准备工作
1. 头文件、矩阵数组等声明
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define maxResolutionNumber 128 //最大解决方案数
#define maxFactorNumber 128 //最大因素个数
float RI[]={0,0,0.58,0.90,1.12,1.24,1.32,1.41,1.45,1.49};
//三维数组,分别表示矩阵的行,列坐标,和存放的字符串值。
//不能使用char* Matrix[maxYSNumber][maxYSNumber],否则只能存放字符串地址。
//使用字符串形式保存,需要计算时可以使用atof转换为了float型
typedef char Matrix[maxFactorNumber][maxFactorNumber][128];
typedef float NormalizedMatrix[maxFactorNumber][maxFactorNumber];
typedef float weightVector[128];//这里只定义了一个向量,作为过渡使用,直接存入矩阵。
Matrix mCriterionLayer;//准则层次比较矩阵
NormalizedMatrix mmCriterionLayer;
Matrix factors[maxResolutionNumber];//因素比较矩阵集合,最多存放 maxResolutionNumber 个矩阵
NormalizedMatrix nFactors[maxResolutionNumber];
Matrix result;//准则层次比较矩阵
2. 读取Excel文件
//从cvs文件中读取矩阵信息
//读取文件内容到矩阵m
void readMatrix(char * filePath,Matrix m){
FILE *fp = NULL;
char *line,*record;
char buffer[1024];
int x=0,y=0,n=0;
if ((fp=fopen(filePath,"r")) != NULL){
char delims[] = ",";
wchar_t *result = NULL;
//当没有读取到文件末尾时循环继续
while (line = fgets(buffer, sizeof(buffer), fp)){
line[strlen(line)-1]='\0';//去除\r\n,无法通过查找\r或\n来处理,但确实先执行\r,将光标移动到第一个字符钱,然后往下一行。可能vc2010对回车的解释看做一个字符?
record = strtok(line, ",");
while (record){
//考虑到小数点以及结束符,自己使用128,而不要用sizeof。
memcpy(m[x][y],record,128/*sizeof(record)+3*/);
record = strtok(NULL, ",");
y++;
}
y=0;
x++;
}
fclose(fp);
fp = NULL;
}
}
具体见下面的链接
https://blog.csdn.net/weixin_41958234/article/details/105681204
3. 辅助函数
3.1打印矩阵
//打印矩阵
void printMatrix(Matrix m,int n){
int i,j;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(is_in(m[i][j],'*')!=-1)
printf("\t");
else if(atof(m[i][j])>0&&atof(m[i][j])<10)//为了解决精度显示问题
printf("%.3f \t",atof(m[i][j]));
else
printf("%s \t",m[i][j]);
}
puts("");
}
}
3.2判断字符串中是否包含某个字符,并返回它所在的位置
int is_in(char*s, char c){
int n=0;
while(*s != '\0'){
if(*s == c){
return n;
}
else{
s++;n++;
}
}
return -1;
}
4. 阶段成果展示
为了测试方便,把需要用户输入的部分都注释掉,采用了自己赋值的方式。程序有一些规定用户必须准守:
- 结果矩阵文件的路径和名称必须为:data/最后计算结果.csv
- 准则层矩阵五年级的路径和名称必须为:data/准则层次比较矩阵.csv
- csv表格中的,如果表各项没有内容,必须使用*占位。
这样程序使用会比较方便,相应于我们自己定义的一个框架,使用者必须准守,当然也可以改成用户输入的方式。
int main()
{
int i,j;
char MatrixName[120];
weightVector wv;
int factorNum=5,solutionNum=3;
//puts("请输入因素个数:");
//scanf("%d",&factorNum);
//puts("请输入方案个数:");
//scanf("%d",&solutionNum);
//puts("---------------结果矩阵:----------------");
readMatrix("data/最后计算结果.csv",result);
printMatrix(result,11);
puts("---------------准则层比较矩阵:----------------");
readMatrix("data/准则层次比较矩阵.csv",mCriterionLayer);
printMatrix(mCriterionLayer,factorNum+1);
puts("---------------因素判断矩阵:----------------");
//for( i=0;i<factorNum;i++)
//{
// printf("请输入矩阵cvs相对路径:");
// scanf("%s",MatrixName);
// readMatrix(MatrixName,factors[i]);
// printMatrix(factors[0],solutionNum+1);
// puts("");
//}
puts("--景色判断矩阵:");
readMatrix("data/景色判断矩阵.csv",factors[0]);
printMatrix(factors[0],solutionNum+1);
puts("");
puts("--费用判断矩阵:");
readMatrix("data/费用判断矩阵.csv",factors[1]);
printMatrix(factors[1],4);
puts("");
puts("--居住判断矩阵:");
readMatrix("data/居住判断矩阵.csv",factors[2]);
printMatrix(factors[2],4);
puts("");
puts("--饮食判断矩阵:");
readMatrix("data/饮食判断矩阵.csv",factors[3]);
printMatrix(factors[3],4);
puts("");
puts("--旅途判断矩阵:");
readMatrix("data/旅途判断矩阵.csv",factors[4]);
printMatrix(factors[4],4);
puts("");
}
运行结果如下,这里只是把cvs文件中的内容读取到了我们的数组当中。
准备工作都做完了下面开始真真进入到计算部分。
计算
1. 矩阵标准化
//矩阵标准化,标准化之后的结果存入新的矩阵。
void normalizeMatrix(Matrix m,NormalizedMatrix nm,int n){
int i,j;
float sum;
for(j=1;j<n;j++){
sum=0;
for(i=1;i<n;i++){
sum+=atof(m[i][j]);
}
for(i=1;i<n;i++){
nm[i-1][j-1]=atof(m[i][j])/sum;
}
}
}
2.计算权重
//计算权重,向量相乘
void countWeight(NormalizedMatrix nm,int n, weightVector returnValue){
int i,j;
//nm是标准化之后的矩阵,sum为因子的个数,也就是n-1
float sum=n-1,subSum;
//求每个因素的子和,小计。然后除以总和sum得到权重值
for(i=0;i<n;i++){
subSum=0;
for(j=1;j<n;j++)
subSum+=nm[i][j];
returnValue[i]=subSum/sum;
}
}
3.将值写入结果矩阵
//将向量值写入结果矩阵。
//col为插入result的第几列,n为weightVector的有效长度
void insertResult(weightVector v,int col, int n){
int i,j;
for(i=0;i<n;i++)
sprintf(result[i+1][col],"%.3f",v[i]);
}
4.阶段成果展示
这里将准则层和因素的判断矩阵分开处理。
int main()
{
... ...
//准则层:标准化矩阵值、计算准则层权重、将结果插入结果矩阵
normalizeMatrix(mCriterionLayer,mmCriterionLayer,factorNum+1);
countWeight(mmCriterionLayer,factorNum,wv);
insertResult(wv,factorNum+1,factorNum);
//计算判断因素的权重
for(i=0;i<factorNum;i++){
normalizeMatrix(factors[i],nFactors[i],solutionNum+1);
countWeight(nFactors[i],solutionNum,wv);
insertResult(wv,i+1,solutionNum);
}
puts("---------------计算结果:----------------");
printMatrix(result,max(factorNum+3,solutionNum+7));
}
5.计算 、CI,CR
float countLambda(Matrix m,weightVector v,int n){
int i,j;
float AlambdaDivLambda,sum=0;
for(i=0;i<n;i++){
AlambdaDivLambda=0;
for(j=0;j<n;j++){
AlambdaDivLambda+=atof(m[i+1][j+1])*v[j];
}
sum+=AlambdaDivLambda/v[i];
}
return sum/n;
}
float countCI(weightVector v,int n){
return(v[n]-n)/(n-1);
}
float countCR(weightVector v,int n){
return(v[n+1])/RI[n-1];//CI/CR
}
6.阶段成果展示
int main(){
... ...
//计算判断因素的权重
for(i=0;i<factorNum;i++){
... ...
wv[solutionNum]=countLambda(factors[i],wv,solutionNum);
wv[solutionNum+1]=countCI(wv,solutionNum);
wv[solutionNum+2]=RI[solutionNum-1];
wv[solutionNum+3]=countCR(wv,solutionNum);
insertResult(wv,i+1,solutionNum+4);
}
puts("---------------计算结果:----------------");
printMatrix(result,max(factorNum+3,solutionNum+7));
}
7. 计算总排序权重
//nS:方案数,nF:因素数
void countTotalWeight(Matrix m,int nS,int nF,weightVector v){
int i,j;
float subsum;
for(i=0;i<nS;i++){
subsum=0;
for(j=0;j<nF;j++)
subsum+=atof(m[i+1][j+1])*atof(m[j+1][nF+1]);
v[i]=subsum;
}
}
8.计算总排序一致性指标
//nS:方案数,nF:因素数
float countTotalCi(Matrix m,int nS,int nF){
int i;
float totalCi=0;
for(i=0;i<nS;i++)
totalCi+=atof(m[nS+2][i+1])*atof(m[i+1][nF+1]);
return totalCi;
}
9.阶段展示
int main{
......
countTotalWeight(result,solutionNum,factorNum,wv);
insertResult(wv,factorNum+2,solutionNum);
sprintf(result[solutionNum+6][3],"%.3f",RI[solutionNum-1]);
sprintf(result[solutionNum+6][1],"%.3f",countTotalCi(result,solutionNum,factorNum));
sprintf(result[solutionNum+6][5],"%.3f",countTotalCi(result,solutionNum,factorNum)/RI[solutionNum-1]);//总排序指标率
if(countTotalCi(result,solutionNum,factorNum)/RI[solutionNum-1]<0.1)
sprintf(result[solutionNum+6][7],"%s","通过");
else
sprintf(result[solutionNum+6][7],"%s","拒绝");
puts("---------------计算结果:----------------");
printMatrix(result,max(factorNum+3,solutionNum+7));
return 0;
}
调整main函数,支持用户输入,以便支持不同的需求
int main(){
int i,j;
char MatrixName[120];
weightVector wv;
int factorNum=5,solutionNum=3;
puts("请输入因素个数:");
scanf("%d",&factorNum);
puts("请输入方案个数:");
scanf("%d",&solutionNum);
//puts("---------------结果矩阵:----------------");
readMatrix("data/最后计算结果.csv",result);
printMatrix(result,11);
puts("---------------准则层比较矩阵:----------------");
readMatrix("data/准则层次比较矩阵.csv",mCriterionLayer);
printMatrix(mCriterionLayer,factorNum+1);
puts("---------------因素判断矩阵:----------------");
for( i=0;i<factorNum;i++){
printf("请输入矩阵cvs相对路径:");
scanf("%s",MatrixName);
readMatrix(MatrixName,factors[i]);
printMatrix(factors[0],solutionNum+1);
puts("");
}
//puts("--景色判断矩阵:");
//readMatrix("data/景色判断矩阵.csv",factors[0]);
//printMatrix(factors[0],solutionNum+1);
//puts("");
//puts("--费用判断矩阵:");
//readMatrix("data/费用判断矩阵.csv",factors[1]);
//printMatrix(factors[1],4);
//puts("");
//puts("--居住判断矩阵:");
//readMatrix("data/居住判断矩阵.csv",factors[2]);
//printMatrix(factors[2],4);
//puts("");
//puts("--饮食判断矩阵:");
//readMatrix("data/饮食判断矩阵.csv",factors[3]);
//printMatrix(factors[3],4);
//puts("");
//puts("--旅途判断矩阵:");
//readMatrix("data/旅途判断矩阵.csv",factors[4]);
//printMatrix(factors[4],4);
//puts("");
normalizeMatrix(mCriterionLayer,mmCriterionLayer,factorNum+1);
//printMatrix(mCriterionLayer,6);
//计算准则层权重
countWeight(mmCriterionLayer,factorNum,wv);
insertResult(wv,factorNum+1,factorNum);
//计算判断因素的权重
for(i=0;i<factorNum;i++){
normalizeMatrix(factors[i],nFactors[i],solutionNum+1);
countWeight(nFactors[i],solutionNum,wv);
wv[solutionNum]=countLambda(factors[i],wv,solutionNum);
wv[solutionNum+1]=countCI(wv,solutionNum);
wv[solutionNum+2]=RI[solutionNum-1];
wv[solutionNum+3]=countCR(wv,solutionNum);
insertResult(wv,i+1,solutionNum+4);
}
countTotalWeight(result,solutionNum,factorNum,wv);
insertResult(wv,factorNum+2,solutionNum);
sprintf(result[solutionNum+6][3],"%.3f",RI[solutionNum-1]);
sprintf(result[solutionNum+6][1],"%.3f",countTotalCi(result,solutionNum,factorNum));
sprintf(result[solutionNum+6][5],"%.3f",countTotalCi(result,solutionNum,factorNum)/RI[solutionNum-1]);//总排序指标率
if(countTotalCi(result,solutionNum,factorNum)/RI[solutionNum-1]<0.1)
sprintf(result[solutionNum+6][7],"%s","通过");
else
sprintf(result[solutionNum+6][7],"%s","拒绝");
puts("---------------计算结果:----------------");
printMatrix(result,max(factorNum+3,solutionNum+7));
return 0;
}
大功告成!