数学余数在计算机的用途
余数
1.余数的特性
- 整数岁没有边界的,它可能岁正无穷大,也可能是正无穷小,余数却总岁在一个固定的范围内。生活中余数可以用来计算星期,web编程中可以用在分页中。
2.同余定理
- 两个整数a和b,如果它们除以正整数m得到余数相等,我们就可以说,a和b对于模m同余。同余定理其实就是用来分类的。
3.求余过程就是个哈希函数
- 每个编程语言都有对应的哈希函数。哈希有的时候也会被翻译成散列,简单来说就是将任意长度输入,通过哈希算法压缩为某一固定长度输出。
一个简单的加密规则
先对每个三位数的个、十和百位数,都加上一个较大的随机数。
然后将每位上的数都除以 7,用所得的余数代替原有的个、十、百位数;
最后将第一位和第三位交换。
这就是一个基本的加密变换过程。
产生的问题
"假如说,我们要加密数字 625,根据刚才的规则,我们来试试。假设随机数我选择 590127。那百、十和个位分别加上这个随机数,就变成了 590133,590129,590132。然后,三位分别除以 7 求余后得到 5,1,4。最终,我们可以得到加密后的数字就是 415。因为加密的人知道加密的规则、求余所用的除数 7、除法的商、以及所引入的随机数 590127,所以当拿到 415 的时候,加密者就可以算出原始的数据是 625。是不是很有意思?"
正向加密可以理解.
反向解密感觉有点问题呀.
625中间的数字2: (2 + 590127)%7 = 1. 但是(9 + 590127)%7 = 1
那么625和695最终加密后的结果都是415啊.
那就不一定能还原出来原始的值了啊.
另外,如果最后一位数字加密后的结果是0, 交换位置后, 会有麻烦吧.
解决问题所实现的代码如下
# coding:utf-8
DIVIDEND = 7
RAND = 590127
def encrypt(num):
if not isinstance(num, int):
raise TypeError("num is not 'int' object")
# int转为list
num = map(int, str(num))
# 对每位加上随机数
num = map(lambda i:i+RAND, num)
# 保存商和求余
quotient, num = zip(*[(i//DIVIDEND, i%DIVIDEND) for i in list(num)])
# 反转
num = list(num)[::-1]
print(list(num))
# list 转回 int
num = map(str, num)
# num = int(''.join(list(num)))
num = ''.join(list(num)) # 首位余数0则会去除,所以用str
# 返回加密数据和商
return (num, quotient)
def decrypt(num, quotient):
#if not isinstance(num, int):
# raise TypeError("num is not 'int' object")
# int转为list
num = map(int, str(num))
# 反转
num = list(num)[::-1]
# 商和余求值
for i,v in enumerate(num):
num[i] = v + quotient[i] * DIVIDEND
# 对每位减去随机数
num = map(lambda i:i-RAND, num)
# list 转回 int
num = map(str, num)
num = int(''.join(list(num)))
return num
if __name__ == '__main__':
num = 8251
print('加密', num)
en_num, q = encrypt(num)
print(f"加密后{en_num}, 商为{q} \n解密...")
de_num = decrypt(en_num, q)
print(de_num)
其他余数的运用案例
- 最大公约数和最小公倍数
- 哈希表
- 一维转二维
- 对数字分类
- 快速查找
- 加密
- 迭代时防止溢出
- 负载均衡
- 离散存储
- 周期显示数据的功能(轮播图)
- 学号
- 星期
- 星座
- 生肖
- 循环队列
- 1024游戏
- 银行卡的位数
- 周期
- 计算机内存
推荐图书《密码学 c c++语言实现》