C语言计算行列式的值

行列式是线性代数学科中的一项重要内容,而其求值却往往比较繁琐。本程序利用C语言,实现了对行列式的计算求值,极大地提高了运用行列式解题的速度和准确率。

数学原理

本程序依据的数学原理是行列式的完全展开式:
det(A)=∑(j1,j2,⋯ ,jn)∈Sn(−1)τ(j1,j2,⋯ ,jn)a1j1a2j2⋯anjn det(A)=\sum_{(j_1,j_2,\cdots,j_n)\in S_n}(-1)^{\tau(j_1,j_2,\cdots,j_n)}a_{1j_1}a_{2j_2}\cdots a_{nj_n} det(A)=(j1,j2,⋯,jn)∈Sn∑(−1)τ(j1,j2,⋯,jn)a1j1a2j2⋯anjn

其中,τ(j1,j2,⋯ ,jn)\tau(j_1,j_2,\cdots,j_n)τ(j1,j2,⋯,jn)指的是该序列的逆序数。

完整代码

本程序完整代码如下:

c 复制代码
#include <stdio.h>

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int odd_even(int list[], int size) {
    int o_e = 1;
    for (int i = 0; i < size; i++) {
        for (int j = i + 1; j < size; j++) {
            if (list[i] > list[j]) {
                o_e = -o_e;
            }
        }
    }
    return o_e;
}

int last(int list[], int size) {
	for (int i = 0; i < size; i++) {
		if (list[i] != size - i - 1) {
			return 0;
		}
	}
	return 1;
}

void sort(int list[], int size, int first) {
	int smallest, smallestx;
	for (int i = first; i < size - 1; i++) {
		smallest = size;
		for (int j = i; j < size; j++) {
			if (list[j] < smallest) {
				smallest = list[j];
				smallestx = j;
			}
		}
		swap(&list[i], &list[smallestx]);
	}
}

void next(int list[], int size) {
    int bigger, biggerx, first;
    for (int i = size - 2; i >= 0; i--) {
        first = list[i];
        bigger = size + 1;
        for (int j = i + 1; j < size; j++) {
            if (list[j] > first && list[j] < bigger) {
                bigger = list[j];
                biggerx = j;
        	}
    	}
    	if (bigger < size + 1) {
            swap(&list[i], &list[biggerx]);
            sort(list, size, i + 1);
            return;
        }
    }
}

int main() {
    
	int n;
    printf("n = ");
    scanf("%d", &n);
    
    int nums[n];
    for (int i = 0; i < n; i++) {
        nums[i] = i;
    }
    
    int det[n][n];
    for (int r = 0; r < n; r++) {
        printf("row %d: ", r + 1);
        for (int c = 0; c < n; c++) {
            scanf("%d", &det[r][c]);
        }
    }
    
    int result = 0, r;
    while (1) {
        r = odd_even(nums, n);
        for (int k = 0; k < n; k++) {
            r *= det[k][nums[k]];
        }
        result += r;
        if (last(nums, n)) {
        	printf("%d", result);
        	return 0;
		}
		else {
			next(nums, n);
		}
    }
}

代码解释

下面对本程序的代码逐段地进行拆解。

数组交换函数swap

c 复制代码
void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

该函数能将数组中两个元素互换位置,实际上是通过使其指针分别指向对方的值来实现的。

排列奇偶性确定函数odd_even

c 复制代码
int odd_even(int list[], int size) {
    int o_e = 1;
    for (int i = 0; i < size; i++) {
        for (int j = i + 1; j < size; j++) {
            if (list[i] > list[j]) {
                o_e = -o_e;
            }
        }
    }
    return o_e;
}

该函数的返回值就是完全展开式中的系数:
(−1)τ(j1,j2,⋯ ,jn) (-1)^{\tau(j_1,j_2,\cdots,j_n)} (−1)τ(j1,j2,⋯,jn)

由于真正的逆序数并不影响计算结果,真正起作用的只是逆序数的奇偶性,奇数时系数为-1,偶数时系数为1,因此该函数的返回值o_e就是1或-1,这也便于后续计算。

遍历结束判断函数last

c 复制代码
int last(int list[], int size) {
	for (int i = 0; i < size; i++) {
		if (list[i] != size - i - 1) {
			return 0;
		}
	}
	return 1;
}

由于该函数需要将从1到n的序列j1,j2,⋯ ,jnj_1,j_2,\cdots,j_nj1,j2,⋯,jn完整地遍历一遍,所以需要确定何时遍历终止。具体而言,就是当jk=n−k−1j_k=n-k-1jk=n−k−1时遍历终止,即序列完全反向了。

排序函数sort

c 复制代码
void sort(int list[], int size, int first) {
	int smallest, smallestx;
	for (int i = first; i < size - 1; i++) {
		smallest = size;
		for (int j = i; j < size; j++) {
			if (list[j] < smallest) {
				smallest = list[j];
				smallestx = j;
			}
		}
		swap(&list[i], &list[smallestx]);
	}
}

程序运行的某些步骤中,需要用到将序列从某一项开始至最后一项这一片段从小到大排列这一操作,这可以由本函数来实现。参数first指的是需要执行排序操作的第一项。

事实上,该函数也可以用递归的方式实现。

找到下一个序列函数next

c 复制代码
void next(int list[], int size) {
    int bigger, biggerx, first;
    for (int i = size - 2; i >= 0; i--) {
        first = list[i];
        bigger = size + 1;
        for (int j = i + 1; j < size; j++) {
            if (list[j] > first && list[j] < bigger) {
                bigger = list[j];
                biggerx = j;
        	}
    	}
    	if (bigger < size + 1) {
            swap(&list[i], &list[biggerx]);
            sort(list, size, i + 1);
            return;
        }
    }
}

该函数的作用是以从小到大的顺序找到下一个排列,不断调用该函数就可以遍历所有的排列,做到不重不漏。具体来说,遍历的方法是从排列的末尾开始作调整,逐步交换,例如:
1,2,3→1,3,2→2,1,3→2,3,1→3,1,2→3,2,1 1,2,3\rightarrow 1,3,2\rightarrow 2,1,3\rightarrow 2,3,1\rightarrow 3,1,2\rightarrow 3,2,1 1,2,3→1,3,2→2,1,3→2,3,1→3,1,2→3,2,1

一次next函数相当于实现一个箭头,调用多次即可遍历所有排列情况。

主函数

c 复制代码
int main() {
    
	int n;
    printf("n = ");
    scanf("%d", &n);
    
    int nums[n];
    for (int i = 0; i < n; i++) {
        nums[i] = i;
    }
    
    int det[n][n];
    for (int r = 0; r < n; r++) {
        printf("row %d: ", r + 1);
        for (int c = 0; c < n; c++) {
            scanf("%d", &det[r][c]);
        }
    }
    
    int result = 0, r;
    while (1) {
        r = odd_even(nums, n);
        for (int k = 0; k < n; k++) {
            r *= det[k][nums[k]];
        }
        result += r;
        if (last(nums, n)) {
        	printf("%d", result);
        	return 0;
		}
		else {
			next(nums, n);
		}
    }
}

n是行列式的阶数。本函数默认行列式中的数值均为整数(不限正负),若有必要引入浮点数,只需将程序中的int类型改为double或其他即可。在用户输入行列式各行各列的数值后,程序就会根据行列式的完全展开式进行计算,遍历完所有情形直至last函数的返回值为1为止,输出行列式的值。

运行结果示例

相关推荐
sunshine22 girl2 小时前
Java学习二 基本语法2, 算术运算符
java·学习
2601_966949652 小时前
为什么量化策略需要大量历史股票数据?从回测可信度理解数据规模
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
niucloud-admin2 小时前
JAVA V6 多商户商城 开发文档——插件目录结构
java·开发语言
滕州市燕猫虎计算机科技工作室个体工商户2 小时前
Java锁
java·开发语言
派葛穆3 小时前
Lerobot -飞特舵机ST-3215双舵机联动(ESP_NOW)
c语言
多加点辣也没关系3 小时前
JavaScript|第31章:表单与控件
开发语言·javascript·ecmascript
菜鸟~noob2333 小时前
【电子战】 第09篇:阵列信号处理——波束形成、MVDR、MUSIC【含matlab代码】
开发语言·matlab·信号处理
ocean21033 小时前
2025-2026年Python面试高频知识点洞察
开发语言·python·面试·python八股文
零依赖极客3 小时前
Day 6·1 ARMv8.2 dotprod——vdotq_s32 一条指令做 4 个点积
c语言·开发语言·人工智能·矩阵·arm·vllm
衡石科技5 小时前
Data_Agent记忆机制与经验复用衡石分析智能体会话记忆与长期学习技术解析
人工智能·科技·学习·算法·企业级bi