出处:http://www.cnblogs.com/bigmonkey
本文以学习、研究和分享为主,如需转载,请联系本人,标明做者和出处,非商业用途!
扫描二维码关注公众号“我是8位的”
程序设计课程老是充满趣味,在学习了判断和循环后就能够编写一些有意思的代码。记得我在初学编程时,老师曾出过一个题目:找出两个整数的最大公约数。当时我在黑板上写下了本身的实现方式:算法
1 def gcd(a, b): 2 if a == b: 3 return a 4 5 if a < b: 6 a,b = b,a 7 8 result = [i for i in range(1, b + 1) if a % i == 0 and b % i == 0] 9 10 return result.pop()
运行结果是正确的,回到座位上,我为此高兴了两分钟。编程
后来老师写出了另外一个实现:数据结构
1 def gcd(a, b): 2 if b == 0: 3 return a 4 else: 5 return gcd(b, a % b)
个人第一反应是:“嗯?”app
遗憾的是,我并无对这段代码深究,只是简单的记住了这种方法,反正都交给计算机计算,何须在意快慢呢?post
后来学了数据结构,知道了用大O评估算法效率,我这才开始从新审视那段寻找最大公约数的代码——它实际上使用了传说中的“展转相除”,要真正弄清楚前因后果,还要从整数提及……学习
咱们都曾经用笨拙的声音从1数到10,这大概是人生中第一次接触数学。稍大一点后,懂得了零的概念,再后来知道了有负数存在……这些美好的记忆都有整数伴随在左右。随着年龄的增加和知识的提高,咱们知道了更多关于整数的知识,这其中就包括整除和余数。spa
数学中是以数轴分段的方式定义整除的,若是n是一个正整数,那么能够用n的倍数将数轴分红不少段:设计
若是将一个整数m放在数轴上,那么m将正好位于qn和(q+1)n之间,其中q也是一个整数:3d
若是m正好是n的整数倍,那么m=qn,不然能够写成m=qn+r形式,qn是在m左侧最近的n的整数倍,r是qn到m的距离。若是把两种状况合并,那么m老是能够写成下面的形式:code
对于特定的n来讲,m的表达式惟一的,这种表达式叫作欧几里德算式,也叫作除法算式。
看着挺唬人,其实欧几里德算式有更常见的描述:若是m,n都是整数,而且n≠0,那么老是存在q和r,0≤r<|n|,使得m有惟一的表达式:
其中q是商,r是余数,若是r=0,则称m 可以被n整除,或n能整除m,记做n|m。看来欧几里德算式只不过是从代数上解释了什么是整除,什么是余数。
示例 找出q和r
1和2比较简单:
3可能会出点差错:
计算机运行的结果:
看来计算机认为是另外一种答案:
定义终于显现出做用了,在余数的定义中0≤r<|n|,r=-1不知足这个条件,因此正确答案是q=-3,r=4。
整除有一些被人们熟知的性质,若是a,b,c都是整数,则:
1. 若是a|b且a|c,则a|(b+c)
2. 若是a|b,则a|cb
3. 若是a|b且b|c,则a|c
因为0不能做为除数,因此a|b包含的默认条件是a≠0。
此外还有一个推论,若是a,b,c都是整数,当a|b且a|c时,对于任意整数m和n,都有a|(mb+nc)。
除法是乘法的逆运算,这些性质和推论其实都是根据乘法的分配律和结合律推导而来的。
整数的故事中少不了素数,它的另外一个名称是质数(prime number),是一种大于1整数。素数是这样定义的:设p是大于1的正整数,若是能整除p的正整数只有p和1,那么p就是一个素数。其中1比较特殊,它不是素数,是单位数。2,3,5,7,11是素数,4,6,8,10,12不是素数。
看起来判断一个整数是不是素数很简单,但这句话仅适用于较小的整数,稍大一点的整数就没那么容易判断了,1234567是不是素数?给你10秒钟时间。
这种复杂的问题仍是交给计算机去处理:
1 # 判断a是不是素数 2 def is_prime(a): 3 if a < 2: 4 return False,a 5 elif a == 2: 6 return True,a 7 8 # 用从 2 到 a-1 之间的每一个数除以a,看看那个能被整除 9 divisors = [x for x in range(2, a) if a % x == 0] 10 11 return len(divisors) == 0,divisors 12 13 print(is_prime(1234567))
is_prim返回一个包含两个元素的元组,第一个元素回答了a是不是素数,另外一个回答了除了1和自身外,a还有哪些约数。
结果显示1234567是不一个素数,除了1和自身外,它还有127和9721两个因数。
is_prime方法可以正确运行,但仍然有改进的余地。根据欧几里德算式,m=qn,q和n两者此消彼长,它们的平衡点是根号m,这意味着只要判断2到根号m间是否存在可以被m整除的数就能够;此外,一个大于2偶数必定不是素数,因此只须要判断奇数便可。由此获得了判断素数的改进版:
1 import math 2 3 # 判断a是不是素数 4 def is_prime_2(a): 5 if a < 2: 6 return False 7 elif a == 2: 8 return True 9 elif a % 2 == 0: 10 return False 11 12 result = True 13 # 取 math.sqrt(a) 的整数部分 14 end = int(math.sqrt(a)) 15 q = 3 16 while(q <= end): 17 if a % q == 0: 18 result = False 19 break 20 q += 2 21 22 return result
整数分解
咱们知道多项式的因式分解,相似地,整数也能够分解,能够将一个正整数写成它的几个约数因子的乘积,这就是整数分解(integer divisorization)。
大于1的整数分解能够更进一步,使每一个因子都是素数。对于每个大于1的正整数m来讲,能够惟一地写成:
其中pi是能整除m的素数因子,p1<p2<…<pt;ki是pi出现的次数。这种表达式被称为整数m的素因子表达式,对于任意m,它的素因子表达式是独一无二的。将m写素因子表达式的过程叫作素因子分解。
素因子表达也从另外一个层面(非素数的层面)定义了素数:若是一个大于1的整数m不是素数,那么m必定可以分解成2个或两个以上素数的乘积,而且这个表达式是惟一的。
示例 写出7、9、20、30的素因子表达式
7自己是一个素数,只能整数分解成1×7,但1并非素数,因此7的素因子表达式就是7自己。
可使用下面的代码进行整数的素因子分解:
1 # 获取a的全部除1和自身外的约数 2 def get_divisors(a): 3 return [x for x in range(2, a) if a % x == 0] 4 5 # 素因子分解 6 def prim_division(a): 7 if is_prime_2(a): 8 return [a] 9 10 result = [] 11 divisors = get_divisors(a) 12 for divisor in divisors : 13 while True: 14 if a % divisor != 0: 15 break 16 if is_prime_2(divisor): 17 result.append(divisor) 18 a /= divisor 19 else: 20 break 21 22 return result
好了,咱们已经知道整数能够素因子分解,可是这有什么用呢?
数学的发展来源于实践,不能用的东西大概也没人去研究。素因子分解的用处还挺多,它能够用来证实素数有无穷个,根号2是无理数,还能够用于密码学、计算复杂理论,甚至用于量子计算等等。接下来就举几个例子,看看素因子分解到底是怎么使用的。
老师:素数有无穷个吗?
同窗:固然了!
老师:为何呢?
同窗:没有为何啊,它固然是无穷的,这还要正明吗?随便给出一个素数,不是很容易的例举出比它更大的素数吗?
老师:可是素数没什么先验的理由必须有无穷多个啊。若是写出一个至关长的,可以绕地球一圈的素数,你能保证必定有一个更大的素数吗?
同窗:……
老师:其实你已经回答了,随便给出一个素数,确实可以例举出比它更大的素数,只不过咱们须要使用反证法来证实。
假设素数的个数是有限的,那么这些素数均可以用集合的形式列举出来:
P就是集合中最大的素数。
根据整数的素因子分解,一个大于1的正整数能够分解成若干个素数的乘积,那么存在一个整数M,它等于Ω中全部元素的乘积加1:
M确定比P更大,P已经被假定是最大的素数,因此M确定不是素数。素因子表达式告诉咱们,M若是不是素数,则必定可以分解成若干个素数的乘积,由于已经假设Ω中包含了全部的素数,因此M也必定可以分解成Ω中若干个元素的乘积。可是如今M除以Ω中的全部元素都会产生余数1,这意味着M只能被M或1整除,因此M也是一个素数,这与“M确定不是素数”矛盾,所以“素数有无穷个”。
注:“素数有无穷个”这一命题最先的证实出如今古希腊数学家欧几里得 (Euclid) 的《几何本来》上,这一命题也所以被称为了 “欧几里得定理” (Euclid's theorem) 或 “欧几里得第二定理” (Euclid's second theorem)。
老师:根号2是一个无理数,它无限不循环,没有尽头。
同窗:为何呢?也许它在绕地球一圈后循环了。
老师:它确实是不循环的,能试试本身证实吗?
同窗:仍是使用反证法吗?
老师:是的。证实的时候别忘了素因子分解。
假设根号2 是一个有理数,根据有理数的定义,有理数是一个整数a和一个正整数b的比,这样一来,就能够得出:
其中a/b不能通分,也就是说a和b是互素的(a和b的公约数只有1)。
如今将等式两侧同时平方:
2b2确定是偶数,因此a2也是偶数,若是a是奇数,则a2也是奇数,因此a只能是偶数,a必定能够素因子分解成:
将a2=2b2等式两侧同时除以2:
a2是偶数,a2/2仍是偶数。a2/2= b2因此b2也是偶数,b仍然是偶数,b能够素因子分解成:
如今2|a而且2|b,这和a、b 互素矛盾,因此根号2是无理数。
待续
做者:我是8位的