主要的事情發三次…
矩陣計算器
矩陣計算器
矩陣計算器
算的實在是心煩,上網找了一篇關於求n階行列式的大佬的代碼
真的是牛逼,附:大佬博客
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>//包含的頭文件不解釋
#define bool int //因爲標準c裏邊沒有bool類型才這麼做
#define false 0
#define true 1
//定義幾個全局變量,無奈之舉
int *c; //將整個行列式的值存到c指向的空間裏
int n = 0;//記錄當前的行列式計算進行了多少步
int a; //方便傳遞行列式的階數
int sum = 0; //記錄每一步行列式計算所累加的結果
int aq(int a) //計算階乘的函數,就不多解釋了
{
int s = 1;
for (int i = 1; i <= a; i ++)
s *= i;
return s;
}
void swap(int *a, int *b) //利用地址傳遞,交換兩個數的值
{
int m = * a;
* a = * b;
*b = m;
}
bool sa(int *l) //計算在行列式計算過程中每一項前邊的符號是正還是負
{
int n = 0;//n爲行列式展開式每一項的逆序數
for (int i = 0; i < a - 1; i ++)
for (int j = i + 1; j < a; j++)
if (l[i] > l[j])n++; //不斷通過條件判斷累加逆序數得出最終的逆序數
if (n % 2 == 0) return false; //若爲正,則返回false
return true;//否則返回true
}
void perm(int *l, int k, int m) //整個程序裏邊的核心函數,找出在不同行不同列的所有組合
{
int i, s = 1;
if (k > m)
{
n++;//每遞歸回來一次,將記錄運行次數加一
for (int j = 0; j < a; j ++)
s *= c[ l[ j ] + a * j ];//算出此次行列式展開式的這項的值
if ( sa( l ) ) s *= -1; //確定這一項的符號
//輸出當前sum內的值(即到當前爲止所得到的結果是多少)
//輸出運行的完成程度(即當前運行的次數除以總次數)
printf("%5d 完成度:%2.2f%%\n", sum += s, n / ( aq( a ) * 0.1 ) * 10 );
}
else //不斷的向內遞歸,就不多解釋了,因爲很多大公司招聘的時候,全排列問題在筆試環節是必出題,百度裏有很多解釋
{
for (i = k; i <= m; i++)
{
swap(l + k, l + i);
perm(l, k + 1, m);
swap(l + k, l + i);
}
}
}
int main()//主函數
{
int *b, //一個輔助變量,在遞歸函數中將b指向的空間內的值進行全排列,也即行列式展開式不同組合的下標
i, //循環中的輔助變量
f, //在格式化輸出行列式的輔助變量
e;//判斷是否退出程序的標誌位
system("color 3e");//設置程序運行的前景色和背景色
u: system("cls");//清空屏幕
printf("請輸入行列式的階數:\n");
scanf("%d", &a);//獲取行列式的階數
b = ( int *) malloc ( sizeof ( int ) * a ); //爲變量申請空間
c = ( int *) malloc ( sizeof ( int ) * a * a );
for ( i = 0; i < a; i++)
* ( b + i ) = i;//爲輔助變量也即行列式下標逐個賦值
for ( i = 0; i < a * a; i++)
{
if ( i % a == 0 )
printf("請依次輸入行列式中第%d行的值(以空格分隔):\n", i / a + 1 ); //提示輸入行列式的值
scanf("%d", c + i );
}
printf("\n\n");
perm( b, 0, a - 1 );//計算行列式的值
printf("\n行列式展開式共有%d項\n", aq( a ) );//打印出來行列式的各種信息
if ( a % 2 != 0 ) f = a + 1;//判斷當前的行列式是偶數行還是奇數行
else f = a;
for ( i = 0; i < a * a; i ++ )
{
if ( i / a + 1 == f / 2 && i % a == 0) //判斷是否達到行列式中間的一行行首
printf("D = ");//輸出“D = ”
else if ( i % a == 0) //判斷是否是每一行的行首,若是則輸出四個空格,保證輸出的格式優美
printf(" ");
if ( i % a == 0) //判斷是否是行首,若是輸出製表符豎線,可與上一句寫到一塊兒
printf("┃");
if ( ( i + 1 ) % a == 0) //判斷是否是行列式某一行的最後一個數
printf("%2d", * ( c + i ) );
else printf("%2d ", * ( c + i ) );//若不是行列式某一行的最後一個數則在數字後邊加一個空格
if ( ( i + 1 ) % a == 0 ) //判斷是否到達一行的行末
printf("┃");
if ( ( i + 1 ) / a == f / 2 && ( i + 1 ) % a == 0) //判斷是否達到行列式中間一行的行末,輸出整個行列式的值
printf(" = %d\n", sum);
else if ( ( i + 1 ) % a == 0 ) //判斷是否到達行末輸出換行
printf("\n");
}
printf("\n\n");
printf("是否繼續?( 1 / 0 )\n");//提示是否退出
scanf("%d", &e);
n = 0;//每次都將都將上一次的運行記錄消除
sum=0;
if ( e == 1 ) goto u; //判斷是否推出
else if ( e == 0 ) exit( 0 );
}