1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > C实现矩阵行列式计算

C实现矩阵行列式计算

时间:2018-09-27 21:14:18

相关推荐

C实现矩阵行列式计算

开始重新学习数学了,然而路途总是不那么平坦,尽管是先挑选的最简单的线性代数,然而一开始就进展不顺

当然我承认数学一直都是一个难以言说的伤痛,但是像什么三阶行列式计算还是老是算错我就有点难以忍受了

于是编写一个程序解决行列式的计算问题,记得好像当初学线性代数的时候也想过编程实现,最终好像因为水平问题没能成功?哎,反正也是很早之前的事情了。

废话少说,先介绍一下大体的思路吧。核心的计算方法采用的是同济大学数学系 工程数学线性代数第六版中的行列式定义,数表中项的全排列的冠以排列逆序确定的符号位的求和(描述不清,详情参考标准表述),我记得我们学校的教材好像并没有这些内容(lll¬ω¬)。于是乎实现方式完全依照定义的方法,在获取到一个矩阵之后,计算出其全排列,然后按排列值取对应项的乘积并计算排列的奇偶逆序确定是否需要乘以-1.

完整代码直接粘贴如下,主要流程就是从stdin读取矩阵数据,计算出行列值,然后以行列值计算全排列,全排列的算法是很久之前写的了,相关细节都忘了,直接改了一下就拿来用了。得到全排列值后就按照定义计算即可。其中主要涉及了几个简单的数学计算比如al_factorial计算阶乘,用来计算全排列需要的存储空间,al_reverseidx计算逆序,直接按照定义来的,感觉可以有更高效的算法,al_fullarray计算全排列。大部分代码其实都是在处理IO,理论上能够处理各种不太完美的输入,但是具体是否还有bug就不得而知了,可能还是存在问题的,不过本来也是写着玩的,也不想过多纠缠于此了。

#include <math.h>#include <stdio.h>#include <stdlib.h>#include <string.h>struct matrix{int c;int r;int*vals;};#define MATRIX_INIT (struct matrix){.c = 0, .r = 0, .vals = NULL}#define MAX_FACTORIAL 10#define MAX_MATRIXMAX_FACTORIALstatic int* al_full_idx;static int al_full_i;int al_factorial(int n);int al_fullarray(int* array, int len);int al_reverseidx(int* array, int len);int matrix_init(struct matrix* m, int r, int c, int* vals, size_t len){if (c <= 0 || r <= 0){puts("Invalid Argument: row or col invalid");return -1;}if (len < (c * r) * sizeof(int)){puts("Invalid Argument: buf size not enough for specific matrix");return -1;}if (r > MAX_MATRIX || c > MAX_MATRIX){puts("matrix size to large");return -1;}m->r = r;m->c = c;m->vals = vals;return 0;}int matrix_det(struct matrix* m){if (m->vals == NULL){puts("Empty matrix");return 0;}if (m->r != m->c){puts("row not equal to col");return 0;}int* array = malloc(sizeof(int) * m->r);for (int i = 0; i < m->r; i++){array[i] = i;}if (al_fullarray(array, m->r) < 0){return 0;}free(array);int fac = al_factorial(m->r);int reverse;int tmpres;int res = 0;for (int i = 0; i < fac; i++){tmpres = 1;for (int j = 0; j < m->r; j++){int row = j;int col = al_full_idx[i * m->r + row];tmpres *= m->vals[row * m->r + col];}if (al_reverseidx(al_full_idx + i * m->r, m->r) % 2 != 0){tmpres *= -1;}res += tmpres;}free(al_full_idx);return res;}static void al_full(int* array, int idx, int len){if (idx == len){for (int i = 0; i < len; i++){al_full_idx[al_full_i++] = array[i];// printf("%d ", array[i]);}// printf("\n");return ;}else{for (int i = idx; i < len; i++){int tmp = array[i];array[i] = array[idx];array[idx] = tmp;al_full(array, idx + 1, len);tmp = array[i];array[i] = array[idx];array[idx] = tmp;}}}int al_fullarray(int* array, int len){if (al_full_idx != NULL){free(al_full_idx);}al_full_idx = NULL;al_full_i = 0;if (len > MAX_FACTORIAL){puts("Factorial: arguments too large");return -1;}al_full_idx = malloc(sizeof(int) * al_factorial(len) * len);if (al_full_idx == NULL){puts("malloc: not enough memory");return -1;}al_full(array, 0, len);return 0;}int al_factorial(int n){if (n > MAX_FACTORIAL){fputs("factorial: Arguments too large", stderr);return -1;}static int res = 1;static int pre = 0;if (pre == n){return res;}res = 1;for (int i = 2; i <= n; i++){res *= i;}pre = n;return res;}int al_reverseidx(int* array, int len){int c = 0;for (int i = 0; i < len; i++){for (int j = 0; j < i; j++){if (array[j] > array[i]){c++;}}}return c;}void puts_int(int i){printf("%d\n", i);return ;}int is_blank(char c){if (c == ' ' || c == '\t' || c == '\n'){return 1;}return 0;}int is_valid_input(char c){if ((c >= '0' && c <= '9') || c == '-' || c == '+'){return 1;}return 0;}void matrix_print(struct matrix* m){for (int i = 0 ; i < m->r; i++){for (int j = 0; j < m->c; j++){printf("%d ", m->vals[i * m->c + j]);}puts("");}return ;}int main(void){struct matrix m = MATRIX_INIT;int count = 0;char c;char cbuf[100];int cint;int ccount = 0;int arr[1024];while ( (c = fgetc(stdin)) != EOF){if (is_blank(c)){if(cbuf[0] != '\0'){if ( (cint = atoi(cbuf)) != 0 || cbuf[0] == '0'){arr[count++] = cint;}ccount = 0;memset(cbuf, 0, sizeof(cbuf));}}else if (is_valid_input(c)){cbuf[ccount++] = c;}else{printf("invalid input detected: %c\n", c);exit(0);}}if (arr[0] != '\0'){if ( (cint = atoi(cbuf)) != 0 || cbuf[0] == '0'){arr[count++] = cint;}}if (count == 0){puts("not capture effective input");exit(0);}int row = (int)sqrt(count);int col = row;if (row * col != count){puts("not NxN matrix");for (int i = 0 ; i < count; i++){puts_int(arr[i]);}return 0;}if (matrix_init(&m, row, col, arr, sizeof(arr)) < 0){exit(0);}printf("\nmatrix you input:\n");matrix_print(&m);puts_int(matrix_det(&m));}

运行截图如下:

环境Windows10,mingw64,powershell,无编译选项

环境Unbuntu1604,gcc,bash,-lm

注意,以终端设备作为标准输入时windows上使用ctrl Z,ubuntu上使用ctrl D发送EOF标识,然而这个东西在两种操作系统/shell上表现并不一致。目前已经发现的问题是在windows powershell输入数据时,输入完成后必须键入一个换行符然后ctrl Z在接一个换行符完成输入操作,否则会使得fgetc读取到一个不可打印字符导致出错,(猜测是那个字符被读入了)。具体shell如何处理标准输入的EOF问题本人尚未深入学习,有兴趣的人可以自行查阅相关文档。

Ubuntu上可以输入完成之后换行接ctrl D,或者两次ctrl D均可。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。