高级语言和低级语言之间需要一个转换的工具:编译器
、解释器
低级语言
- 面向机器的语言,包括机器语言、汇编语言
- 不同的机器不能通用,不同的机器需要不同的机器指令或者汇编程序
高级语言
- 接近自然语言和数学语言的计算机语言
- 高级语言首先要书写源程序,通过编译程序把源程序转换成机器指令的程序
- 1954年正式发布的Fortran语言是最早的高级语言,本意是公式翻译
编译器
编译器是把源代码整个编译成目标代码,执行时不在需要编译器,直接在支持目标代码的平台上运行,这样执行效率比解释执行快很多。比如C和C++等语言的代码被编译成二进制代码(exe程序),在windows平台上执行。
解释器
解释器是一条一条的解释执行源语言。比如Python、JAVA、javascript、PHP就是典型的解释性语言。它们的代码需要被解释器编程中间代码(Bytecode),在虚拟机上运行。
- 编译语言,把源代码转换成目标机器的CPU指令
- 解释语言,解释后转换成字节码,运行在虚拟机上,解释器执行中间代码
- 编译器的优点:执行效率远远高于解释运行的程序
- 解释器的优点:比较容易让用户实现自己跨平台的代码
素数
质数(prime number)又称素数,有无限个。
质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。
判断一个数是否是素数
num = int(input('请输入一个数>>>'))
if num % 2 == 0:
print('该数是质数')
quit()
for i in range(3,int((num**0.5)+1),2):
if num % i == 0:
print('该数不是质数')
break
else:
print('该数是质数')
素数的定义是从2开始到自身的-1的数中找不到一个能整除的,即为素数。
优化点一:可以简化到从2开始到自身开平方的数中找到一个能整除的,即为素数。
优化点二:同时素数也不会被一个偶数整除,所以在range函数中设置步长为2,跳过所有偶数。
求100万以内的素数
start = datetime.datetime.now()
print(2,end=' ')
for i in range(3,1000000,2):
for j in range(3,int((i**0.5))+1,2):
if i % j == 0:
break
else:
print(i,end=' ')
end = datetime.datetime.now()
print(end-start,'s')
测试用时 3.83s 3.56s 3.76s 4.01s 3.84s
start = datetime.datetime.now()
prime = []
flag = True
for i in range(3,1000000,2):
for j in prime:
if j >= (i**0.5)+1:
flag = True
break
if i % j == 0:
flag = False
break
if flag:
prime.append(i)
print([2]+prime)
end = datetime.datetime.now()
print(end-start,'s')
测试用时 5.11s 4.92s 4.93s 5.23s 5.06s
- 因为
一个合数一定可以分解成几个素数的乘积
,也就是说,一个数如果能被一个素数整除就是合数。所以设置一个列表prime接收依次验证所得的素数加快后续的检验。 - 因为我们在提供测试数据的时候已经淘汰了偶数,所以把2暂时移出素数集,减少计算次数。
- 同时在素数的验证中加入
“从2开始到自身开平方的数中找到一个能整除的,即为素数”
的概念,减少取列表中的素数验算自身的次数。 - 素数出现的规律是结尾为1、3、7、9的数,设想过提前与5进行计算排除结尾为5的数。
但是假设1000以内,可以被3整除的数大约为333个,而被5整除的是200个。
并且因为我们已经淘汰了偶数,所有被5整除的数只剩下100个,因此我们没有必要提前用5进行计算处理掉以5结尾的数。
start = datetime.datetime.now()
prime = []
flag = True
for i in range(3,1000000,2):
# k = i ** 0.5 + 1
k = math.sqrt(i) + 1
for j in prime:
if j >= k:
flag = True
break
if i % j == 0:
flag = False
break
if flag:
prime.append(i)
print([2]+prime)
time = (datetime.datetime.now()-start).total_seconds()
print(time)
测试用时 2.24s 2.13s 2.3s 2.05s 2.11s
- 因为如果写成j >= (i**0.5)+1 在每一次循环都要进行重复运算,所以提前在循环外计算,即
k = i ** 0.5 + 1
,以加快速度。 - 同时测试发现使用函数计算k,也就是k=math.sqrt(i)+1。在计算100W数据时只有0.0x秒的优势,差别极小。在计算1000W数据时,大约有0.5s的优势。