C/C++/Java/Go/Rust,Python喊你来打擂:3秒钟内统计出小于1亿的素数个数

news/2024/11/24 13:50:30/

前几天,有个非计算机专业的同学问我,如何快速找出1亿之内的孪生素数——所谓孪生素数,就是差值为2的两个素数。原本以为这是一个很简单的问题,随便用python写了一个方法,没想到却要跑17分钟左右。改用C++试试,受限于我对C/C++的理解程度,仍然慢得无法承受(此处绝无小视C++之意)。这个问题激起了我的兴趣。于是乎,我花了半天时间,尝试了几种方式,最终又对代码做了优化,终于在3秒钟内找出了小于1亿的素数表。

略微得意了3秒钟,突然想到,Python 这个速度究竟是什么水平呢?用 C/C++/Java/Go/Rust 等语言实现起来会不会更快呢?如果大家一起来个擂台赛,会不会很热闹?各位 C/C++/Java/Go/Rust 的高手们,有兴趣一起搞个擂台赛吗?没准儿,CSDN会为这个活动设置奖项呢(哈哈哈。。。)

11月6日追记:今天,有几位朋友在评论区留言,冷嘲热讽,不太友好。一开始我还逐一认真回复,后来想,算了,统一在这里说一下吧:1. 作为从业二十余年的老程序员,从事科学计算多年,深知C/C++语言的效率,也了解目前数学运算的速度,如各位担心我忘记了,请尽量心平气和地提醒我;2. 本文写作的目的,仅仅是出于探讨如何提高python计算速度的目的,并没有轻视某种语言,且在开篇已经声明;3. 所有人都知道速度是python的短板,之所以取这样的名字,不否认有博眼球的用意,但也是想给CSDN提个建议,搞一些跨界活动,给大家弄点纪念品;4. 作为脚本语言python能跑出2.4秒的成绩,你用C++也是2点几秒,即使更快,似乎也没有蔑视嘲讽他人的资格;5. 我已过知天命之年,再激烈的言辞也可以接受,不会删除评论,最大限度尊重言论自由,也请评论者尽量保持平和的心态。

1. 找出1百万以内的质数,大约3秒钟

咸盐稍许,先给出我的最原始的算法。运行 prime_1.py,找出100万以内的质数,大约3秒钟。不要试图尝试更大范围的寻找,那会花更长的时间,长到你无法忍受。

prime_1.py

# -*- coding: utf-8 -*-import sys, time
from math import sqrtdef find_prime(upper):"""找出小于upper的所有质数"""prime_list = list() # 存放找到的质数for i in range(2, upper): # 从2开始,逐一甄别是否是质数is_prime = True # 假设当前数值i是质数for p in prime_list: # 遍历当前已经找到的质数列表if i%p == 0:is_prime = Falsebreakelif p > sqrt(i):breakif is_prime:prime_list.append(i)return prime_listupper = 1000000
t0 = time.time()
prime_list = find_prime(upper)
t1 = time.time()
print('查找%d以内的质数耗时%0.3f秒,共找到%d个质数'%(upper, t1-t0, len(prime_list)))

2. 找出1千万以内的质数,大约12秒钟

3秒钟找出100万以内的质数,这个效率,显然无法用于查找1亿以内的素数。下面的代码,我使用了numpy这个科学计算库,速度提升明显。运行 prime_2.py,找出1千万以内的质数,大约12秒钟。不过要是用它来查找1亿以内的质数,至少需要15分钟。

prime_2.py

# -*- coding: utf-8 -*-import sys, time
import numpy as np"""
网上有文章说,python最强找质数程序,寻找10万以内质数只要30秒哦!运行一下我们这个脚本,找出1千万内的质数,大约11秒
不要尝试找出1亿内的质数,你等不到结果。别说我没告诉你!!!
"""def find_prime(upper):"""找出小于upper的所有质数"""prime_list = list() # 空数组,用于存放找到的质素mid = int(np.sqrt(upper)) # 判断100是否是质数,只需要分别用2,3...等质素去除100,看能否被整除,最多做到100的平方福根就够了nums = np.arange(upper) # 生成0到上限的数组,数组元素的值等于其索引号,相对于python的[0,1,2,3,...]nums[1] = 0 # 数组第1和元素置0,从2开始,都是非0的while True: # 循环primes = nums[nums>0] # 找出所有非0的元素if primes.any(): # 如果能找到p = primes[0] # 则第一个元素为质数prime_list.append(p) # 保存第一个元素到返回的数组nums[p::p] = 0 # 这个质数的所有倍数,都置为0(表示非质素)if p > mid: # 如果找到的质数大于上限的平方根break # 则退出循环else:break # 全部0,也退出循环prime_list.extend(nums[nums>0].tolist()) # nums里面剩余的非0元素,都是质数,合并到返回的数组中return prime_list # 返回结果upper = 10000000
t0 = time.time()
prime_list = find_prime(upper)
t1 = time.time()
print('查找%d以内的质数耗时%0.3f秒,共找到%d个质数'%(upper, t1-t0, len(prime_list)))

3. 找出1亿以内的质数,耗时不到3秒钟!

上面的代码还有优化的空间吗?经过分析发现,numpy 的 ndarray 对象,其元素数量超过一定范围后,效率明显变慢。针对这一点,我做了分块优化。运行 prime_3.py,找出1亿以内的质数,耗时不到3秒钟!

prime_3.py

# -*- coding: utf-8 -*-import sys, time
import numpy as np"""
网上有文章说,python最强找质数程序,寻找10万以内质数只要30秒哦!运行一下我们这个脚本,找出1亿以内的质数,耗时不到3秒,比上面快了大约1万倍
还可以尝试更大的范围,但步子不要太大!!!
"""def find_prime(upper):"""找出小于upper的所有质数"""prime_list = list()mid = int(np.sqrt(upper))nums = np.arange(upper)nums[1] = 0while True:primes = nums[nums>0]if primes.any():p = primes[0]prime_list.append(p)nums[p::p] = 0if p > mid:breakelse:breakprime_list.extend(nums[nums>0].tolist())return prime_listdef fast_find_prime(upper, base=100000, block=20000000):"""快速找出小于upper的所有质数"""if upper <= base:return find_prime(upper)mid = int(np.sqrt(upper))prime_list = find_prime(base)prime_array = np.array(prime_list)prime_array = prime_array[prime_array<=mid]start = basewhile start < upper:end = start + blockif end > upper:end = upperprint((start, end))prime_list.extend(process_func(start, np.copy(prime_array), (start, end)))start += blockreturn prime_listdef process_func(id, primes, task_range):"""执行分块任务的函数primes      - 用以剔除非质数的质数表task_range  - 分块任务的数值范围"""nums = np.arange(task_range[0], task_range[1])for p in primes:k = (p-task_range[0]%p)%pnums[k::p] = 0return nums[nums>0].tolist()upper = 100000000
t0 = time.time()
prime_list = fast_find_prime(upper)
t1 = time.time()
print('查找%d以内的质数耗时%0.3f秒,共找到%d个质数'%(upper, t1-t0, len(prime_list)))

后记

近期有很多朋友通过私信咨询有关Python学习问题。为便于交流,我在CSDN的app上创建了“Python作业辅导”大本营,面向Python初学者,为大家提供咨询服务、辅导Python作业。欢迎有兴趣的同学使用微信扫码加入。

在这里插入图片描述

从博客到公众号,每一篇、每一题、每一句、每一行代码,都坚持原创,绝不复制抄袭,这是我坚守的原则。如果喜欢,请关注我的微信公众号“Python作业辅导员”。

在这里插入图片描述


http://www.ppmy.cn/news/332340.html

相关文章

看到「财富自由」就想吐

这些年&#xff0c;网上关于财富自由的人生故事&#xff0c;可以说是数不胜数。 不过&#xff0c;其中 70% 像是真假参半的凡尔赛炫耀帖&#xff0c;剩下的那 30% 则更像是兜售某些产品的广告。 比如前几天很火的腾讯 35 岁员工准备退休的帖子&#xff0c;就挺能说明问题。 这种…

我在翻译《Thinking in Java》(三)

1.8 单根的继承结构 自从C诞生以来&#xff0c;面向对象程序设计就出现了这样一个问题&#xff1a;是否所有的类最终都应该继承于一个共同的基类&#xff1f;在Java中&#xff08;实际上除C以外所有的OOP语言都是这样&#xff09;给出了肯定的回答&#xff0c;并把最终基类简单…

感知春运(1)车票

现在才说春运会不会有点晚。元宵已过&#xff0c;回家过年返回上班的人大部分都已回来。公交车&#xff0c;超市&#xff0c;马路上又重现往常的人潮涌动&#xff0c;擦肩而过。 今天周末&#xff0c;天气很冷&#xff0c;窗外还刮有缕缕冷风。想想还是算了&#xff0c;窝在家抱…

苹果6s照相快门声音设置_你不知道的8种手机快门启动方式,各有妙用!

如果问各位摄友&#xff0c;你是如何启动手机快门的&#xff1f;99%的摄友可能都会说通过按下界面下方的“大白点儿”。 如果再接着问&#xff0c;你知道还有哪些启动快门的方式吗&#xff1f;很多摄友可能就不太清楚了。 事实上&#xff0c;为了满足在不同情况下都可以随时按下…

SEO服务价格的影响因素(转)

可能是这个行业还比较新的原因吧&#xff0c;大家对SEO价格的把握还是没准儿&#xff0c;所以这里再根据自己最近跟几个客户交流过程中遇到的相关问题&#xff0c;再结合网上一些朋友分享的经验&#xff0c;再写一篇关于网站搜索引擎优化SEO如何报价的问题&#xff0c;并且探索…

2023年的深度学习入门指南(5) - 动手写第一个语言模型

2023年的深度学习入门指南(5) - 动手写第一个语言模型 上一篇我们介绍了openai的API&#xff0c;其实也就是给openai的API写前端。在其它各家的大模型跟gpt4还有代差的情况下&#xff0c;prompt工程是目前使用大模型的最好方式。 不过&#xff0c;很多编程出身的同学还是对于…

程序员参加5月软考高项考试的体会分享,是机会还是坑?

大家好我是陈哈哈&#xff0c;参加了今年5月27日的软考信息项目管理师考试&#xff0c;我深知高项的难度以及需要付出的时间和精力成本&#xff0c;我在3月份工作最忙的阶段毅然决然选择了加入。至于为什么&#xff0c;至少在一个月前我还没搞明白报名的勇气从何而来。作为一名…

复旦的新衣再登Nature!穿在身上能为手机充电

近日&#xff0c;一件来自中国的衣服登上了Nature。 没看出有什么特别&#xff1f;别眨眼&#xff0c;下一秒神奇的事情就发生了&#xff08;注意那个手机&#xff09;。 没错&#xff0c;这件衣服正在给手机无&#xff01;线&#xff01;充&#xff01;电&#xff01; 不是把…