整数的故事(1)

  程序设计课程老是充满趣味,在学习了判断和循环后就能够编写一些有意思的代码。记得我在初学编程时,老师曾出过一个题目:找出两个整数的最大公约数。当时我在黑板上写下了本身的实现方式:算法

 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两个因数。

寻找素数2.0版

  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个或两个以上素数的乘积,而且这个表达式是惟一的。

 

  示例  写出792030的素因子表达式

  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是一个无理数,它无限不循环,没有尽头。

  同窗:为何呢?也许它在绕地球一圈后循环了。

  老师:它确实是不循环的,能试试本身证实吗?

  同窗:仍是使用反证法吗?

  老师:是的。证实的时候别忘了素因子分解。

  假设根号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位的

  出处:http://www.cnblogs.com/bigmonkey

  本文以学习、研究和分享为主,如需转载,请联系本人,标明做者和出处,非商业用途! 

  扫描二维码关注公众号“我是8位的”

相关文章
相关标签/搜索