(前排提示,代码内容在文章中间,末尾是闲聊)
离散数学在在“右复合”的基础上提出了“幂运算”的概念。
设R为A上的关系,n为自然数,则R的n次幂如下:
(1)
为恒等关系。
(2)
=
o
。
咳咳,用上面两个定义可以干很多事情,比如我们知道任意集合上关系的0次幂都是恒等关系,关系矩阵正对角线为1,其余为0。并且用复合堆积可以求更高次幂的R。然后书上列举了一下计算过程(虽然只能看到结果)
小破书,将就看,总之我们的目标是重现书本上的关系矩阵。要用到的算法就是矩阵乘法。百度一下得到关系矩阵的乘法如下:
直接定位到公式结论那部分,从而得到我们要用到编程的算式。又因为矩阵包含行和列的运算,所以基本确认是使用双循环来解决运算问题,录入的话就手动输入,不耽误太多时间。
for(i=0;i<get;i++)
for(j=0;j<get;j++)
for(k=0,s=0;k<get&&s<get;k++,s++)
b[i][j]+=a[i][k]*a[s][j];
for(i=0;i<get;i++)
for(j=0;j<get;j++)
for(k=0,s=0;k<get&&s<get;k++,s++)
answer[i][j]+=b[i][k]*a[s][j];
咳咳,由于实际问题需要改变位置,所以在此之上再加一层循环,得到了基本的算法框架。
这还只是开始,我们下面习惯性的分模块考虑问题:
- 0次幂输出恒等关系。
- 1次幂输出本身。
- 非0偶次幂矩阵复合运算。
- 非1奇次幂矩阵复合运算。
- 书上对负次幂没有定义,这里忽略。
好,四个模块分好,接下来就是模块补充了,看不懂也没关系,下面附上我的源代码,输入请按照关系矩阵的格式输入,避免程序报错。
package hellojava;
import java.util.Scanner;
public class 离散数学计算n次幂 {
public static void main(String[] args) {
int i=0,j=0,k=0,s=0;
int a[][]=new int[10][10] ;
int answer[][]=new int[10][10];
Scanner input = new Scanner(System.in);
System.out.println("离散数学计算n次幂很麻烦?方便来了!");
System.out.print("这里输入矩阵的大小:");
int get=input.nextInt();
for(i=0;i<get;i++)
for(j=0;j<get;j++)
answer[i][j]=0;
System.out.println("开始录入矩阵吧");
for(i=0;i<get;i++)
for(j=0;j<get;j++)a[i][j]=input.nextInt();
while(true) {//循环录入,方便测算多次
System.out.print("要计算多少次幂呢:");
int sqrt=input.nextInt();if(sqrt>=88)break;
else {
if(sqrt==1)//一次幂保留不变
for(i=0;i<get;i++)
for(j=0;j<get;j++)
answer[i][j]=a[i][j];
else if(sqrt%2==1&&sqrt!=1) {//非1奇数幂结果一致
int b[][]=new int[10][10];
for(i=0;i<get;i++)
for(j=0;j<get;j++)
for(k=0,s=0;k<get&&s<get;k++,s++)
b[i][j]+=a[i][k]*a[s][j];
for(i=0;i<get;i++)
for(j=0;j<get;j++)
for(k=0,s=0;k<get&&s<get;k++,s++)
answer[i][j]+=b[i][k]*a[s][j];
}
else if(sqrt%2==0&&sqrt!=0) {//非0偶数幂结果一致
for(i=0;i<get;i++)
for(j=0;j<get;j++)
for(k=0,s=0;k<get&&s<get;k++,s++)
answer[i][j]+=a[i][k]*a[s][j];
}
else if(sqrt==0) {//0次幂默认恒等关系
for(i=0;i<get;i++)
for(j=0;j<get;j++)
answer[i][j]=0;
for(i=0;i<get;i++)
answer[i][i]=1;
}
else System.out.println("有点小错误呢,检查一下输入是否正确");
for(i=0;i<get;i++) {if(i!=0)System.out.println();
for(j=0;j<get;j++) System.out.print(answer[i][j]+" ");}
for(i=0;i<get;i++)
for(j=0;j<get;j++)
answer[i][j]=0;
System.out.println();
}
}
System.out.println("感谢使用,拜拜了您内!");
input.close();
}
}
经过书本的检验,这个程序运行的精度没有问题。
俗话说,不能实战的代码不是好代码。既然我要做这个东西,证明我想拿他减少我的重复工作量。于是离散老师很识相的在线上小测验里出了一道计算n次幂的题目。
先把题目转化成程序识别的关系矩阵,然后才能进行接下来的操作。
可以看到,和答案完全一致,但是美中不足的点在于逻辑加有个定义:1+1=1,程序里的需要额外运算,不然就是修改结果数据。无论哪种都不影响正常使用,注意别填错就行啦。
最后想聊聊代码之外的问题,有人说学代码有什么用,学离散有什么用。我觉得与其别人告诉你怎么用,不如自己去发掘用法。就好像有人告诉你数学就是拿来算账的,那你的思维也只会局限在账本的三寸天地。放眼望去,航空航天的轨道运行、枪手射击的概率论、对已知目标的线性规划,不都是生活中常见的运用吗,在面临越庞大的数据,凭借直觉和人脑的计算就如同愚公移山,这时候编程的优势就体现出来了,一流的速度配合精巧的逻辑运算,就是一个小宇宙。学科间的相互融合应该是如同我们喝水一样的理所当然,而不是等着书本去定义,拾人牙慧的事谁都能干,又怎么缺你一个呢对吧。
如果上面的这段话对你有用的话,也请不要把我的话当真,因为这只是一个大一新生的一己之见。理解的话就谢谢啦!