鱼C论坛

 找回密码
 立即注册
查看: 3992|回复: 12

[已解决]求素数有一段看不懂

[复制链接]
发表于 2022-10-22 16:51:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x

已经用另一段代码实现了求素数效果,但标准答案其中一段看不懂

  1. def IsPrime(n):
  2.     if n <= 1 or n % 2 == 0 and n != 2:
  3.         return False
  4.     elif n == 2:
  5.         return True
  6.     else:
  7.         for i in range(3,n,2):
  8.             if n % i == 0:
  9.                 return False
  10.             if i * i > n:
  11.                 break
  12.     return True
  13. for i in range(100):
  14.     if( IsPrime(i)):
  15.         print(i,end = " ")
复制代码



if i * i > n:
                break


这段看不懂什么含义
最佳答案
2022-10-22 17:00:20
本帖最后由 jackz007 于 2022-10-22 18:13 编辑

        这个代码可否看懂?
  1. def IsPrime(n):
  2.     r = False
  3.     if n > 1:
  4.         for i in range(2 , n):
  5.             if n % i == 0 : break
  6.         else:
  7.             r = True
  8.     return r

  9. for i in range(100):
  10.     if( IsPrime(i)):
  11.         print(i,end = " ")
复制代码

        至于为什么
  1. if i * i > n:
  2.     break
复制代码

         看看下面的代码:
  1. n = 256
  2. for i in range(2 , n):
  3.     if n % i == 0:
  4.         print("%3d = %3d x %3d" % ( n , n // i , i))
复制代码

         这个代码是用来寻找 256 所有因子的,再来看看运行结果
  1. D:\[00.Exerciese.2022]\Python>python x.py
  2. 256 = 128 x   2
  3. 256 =  64 x   4
  4. 256 =  32 x   8
  5. 256 =  16 x  16
  6. 256 =   8 x  32
  7. 256 =   4 x  64
  8. 256 =   2 x 128
复制代码

         明眼人一看就能明白,循环过程多用了近一倍,以 256 = 16 x 16 为界,后半部分其实就是重复了前半部分的结果而已,完全没有必要。所以,对于寻找 256 的因子而言,只需要在 2 ~ 16 ,也就是 2 ~ sqrt(256) 的范围内寻找即可,这样可以避免多余的计算和判断,有效提高代码效率。
        那么,现在再来看看这条语句
  1.     if i * i > n  :
  2.         break
复制代码

        其中的道理就不用多作解释了吧?
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-10-22 16:56:08 From FishC Mobile | 显示全部楼层
求素数时,为了减少循环次数,不都是用这玩意吗,如果检索到平方根还是没有发现因子,就不用继续扫描了,原因可以自己思考

评分

参与人数 1鱼币 +1 收起 理由
jcpython2 + 1 感谢提示

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-22 17:00:20 | 显示全部楼层    本楼为最佳答案   
本帖最后由 jackz007 于 2022-10-22 18:13 编辑

        这个代码可否看懂?
  1. def IsPrime(n):
  2.     r = False
  3.     if n > 1:
  4.         for i in range(2 , n):
  5.             if n % i == 0 : break
  6.         else:
  7.             r = True
  8.     return r

  9. for i in range(100):
  10.     if( IsPrime(i)):
  11.         print(i,end = " ")
复制代码

        至于为什么
  1. if i * i > n:
  2.     break
复制代码

         看看下面的代码:
  1. n = 256
  2. for i in range(2 , n):
  3.     if n % i == 0:
  4.         print("%3d = %3d x %3d" % ( n , n // i , i))
复制代码

         这个代码是用来寻找 256 所有因子的,再来看看运行结果
  1. D:\[00.Exerciese.2022]\Python>python x.py
  2. 256 = 128 x   2
  3. 256 =  64 x   4
  4. 256 =  32 x   8
  5. 256 =  16 x  16
  6. 256 =   8 x  32
  7. 256 =   4 x  64
  8. 256 =   2 x 128
复制代码

         明眼人一看就能明白,循环过程多用了近一倍,以 256 = 16 x 16 为界,后半部分其实就是重复了前半部分的结果而已,完全没有必要。所以,对于寻找 256 的因子而言,只需要在 2 ~ 16 ,也就是 2 ~ sqrt(256) 的范围内寻找即可,这样可以避免多余的计算和判断,有效提高代码效率。
        那么,现在再来看看这条语句
  1.     if i * i > n  :
  2.         break
复制代码

        其中的道理就不用多作解释了吧?

评分

参与人数 1荣誉 +1 鱼币 +1 收起 理由
jcpython2 + 1 + 1 感谢耐心赐教

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-22 23:24:52 | 显示全部楼层
本帖最后由 jcpython2 于 2022-10-22 23:36 编辑
jackz007 发表于 2022-10-22 17:00
这个代码可否看懂?

        至于为什么


抱歉老哥,奋斗五个小时了,我还没解出来

我只能回答你你那段代码我应该是理解的

  1. def IsPrime(n):
  2.     r = False
  3.     if n > 1:
  4.         for i in range(2 , n):
  5.             if n % i == 0 : break
  6.         else:
  7.             r = True
  8.     return r

  9. for i in range(100):
  10.     if( IsPrime(i)):
  11.         print(i,end = " ")
  12. """"""""""

  13. 这段代码看明白


  14. 函数内假设代入7
  15. 分别循环 % 2 3 4 5 6

  16. 余 2 得1
  17. 余 3 得1
  18. 余 4 得3
  19. 余 5 得2
  20. 余 6 得1

  21. 7内所有数均没有触发==0break跳出循环

  22. for循环自动进入else部分

  23. r 赋值为True

  24. 这里主要通过质数的一个判定条件:质数成立的条件是1和自身外没有其他因子(除不尽,必然有余数)
  25. 1和这个数自身先不考量,也就是某数除去 2到这个数-1 范围内 都除不尽
  26. 他必然只能除1和自己能除尽
  27. 所以他是质数

  28. PS:这里学到了for完没停止循环就自动进入else用法
  29. """""""""
复制代码


至于我那个 i * i > n 问题,我试着搜索质数 因子 余数等数学概念并结合你说的内容,都找不到我能理解到的内容。
我整晚在一步一步一个数一个数代入代码中,最后别说逻辑了,脑子转不过来了,我明早早起再试试

现在我能勾勒到的就是
54.jpg
减低循环检索次数,增加程序效率,但个中原理无法吃透,可能是数学逻辑我没基础的缘故



以下是我无用功的备注,现在写完脑子乱了,转不过来

  1. def IsPrime(n):
  2.     if n <= 1 or n % 2 == 0 and n != 2:
  3.         #n触发0和1或 n无余数能除尽并且不为2(012为质数)
  4.         return False
  5.     elif n == 2:
  6.         return True
  7.     else:
  8.         for i in range(3,n,2):
  9.             #假设n = 13进入for循环,i为 3_5_7_9_11
  10.             #假设轮到 i = 3
  11.             if n % i == 0:     #13 % 3 == 3  不触发
  12.                 return False
  13.             if i * i > n:      #3 * 3 > 13  不触发 3不触发到跳出,循环继续到5
  14.                 break
  15.     return True


  16. for i in range(20): #假设 i 轮到13代入函数
  17.     if( IsPrime(i)):
  18.         print(i,end = " ")
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-22 23:38:03 | 显示全部楼层
本帖最后由 jackz007 于 2022-10-22 23:47 编辑
jcpython2 发表于 2022-10-22 23:24
抱歉老哥,奋斗五个小时了,我还没解出来

我只能回答你你那段代码我应该是理解的


       3 楼用实例说明的为什么寻找目标数 n 因子时的枚举范围应该是 2 ~ sqrt(n) ,自以为讲解得非常简单、清楚、明白,没想到还是让你没看懂,我想问一下,你到底仔细看了没有?真的就没有明白点什么?再次提示你一下,以 256 = 16 x 16 为轴,上下两边对称位置上的等式是完全一样的。这一点,居然没有让你看出来?
       既然一样,那就只需要循环一半次数就够了呀,这个还不顺理成章???
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-22 23:57:49 | 显示全部楼层
本帖最后由 jcpython2 于 2022-10-23 00:50 编辑
jackz007 发表于 2022-10-22 23:38
3 楼用实例说明的为什么寻找目标数 n 因子时的枚举范围应该是 2 ~ sqrt(n) ,自以为讲解得非常 ...


老哥我对你给出的提示代码是有认真阅读,并且每字每句都看的,我还百度了各个提到的数学概念

如我上面的图片

                               
登录/注册后可看大图


我知道你想引导告诉我范围应该循环一半即可

就像 x = a *b  检查过后无需再检查  x = b * a

我也是遵循这个方向去思考


我代码中的备注
#假设n = 13进入for循环,i为 3_5_7_9_11
#假设轮到 i = 3
#3 * 3 > 13  不触发 3不触发到跳出,循环继续到5


然后i 到5后

i * i > 13 触发return True

确定13为质数????    后面7_9_11不需要再检查


那么……那么

我在写这个回复的时候写到这里我自己纳闷,我想到哪里去?我怎么好像脑子跟手脱钩了?



=============


缓了一下

当判断13的时候  先是判断3,没有跳出循环没返回True,然后到i = 5

if n % i == 0:      #13 % 5 == 3  不触发
      return False

然后

5 * 5 > 13

触发
  1. return True
复制代码


所以当判断13是否素数的时候,理论需要让13 % 2~12

但判断到5的时候就正式确定13就是素数

所以为什么5到就是素数呢


你给的提示,跟这个沾边但我又无法理解到这个点



小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-23 00:53:55 | 显示全部楼层
数学基础差,确实吃不过来,先睡一觉,明日再挣扎
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-24 11:08:31 | 显示全部楼层
1
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-10-24 17:48:18 | 显示全部楼层
本帖最后由 Stubborn 于 2022-10-24 17:59 编辑

什么叫素数,除开1和本身,不能被其他数整除。
针对你的代码而言,下面这一行代码往上处理了什么数字,1,2,和偶数,被剔除。偶数剔除后,筛选的步长则设置为2
  1. for i in range(3,n,2):
复制代码

下面这行代码而言,对一个整数而言,i*i > n 后面可以不用搜锁,你不理解为什么,100可以被整除的数字包括这些[1, 2, 4, 5, 10, 20, 25, 50, 100]。

如果一个整数N可以被整除,你只需要搜索 1 ~ i * i >N ,如果i~N还存在可以被整除的数字,那么结果肯定是比I小。但是1~I的区间,程序已经搜索过。没有必要搜索。
所以综合而言,程序只需要搜索1 ~ i * i >N 范围的数字,这个区间的数字都不能被整除,那么这个数字肯定是一个素数


  1. if i * i > n:  
复制代码

评分

参与人数 1荣誉 +1 收起 理由
jcpython2 + 1 感谢楼主无私奉献!

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-27 16:11:13 | 显示全部楼层
Stubborn 发表于 2022-10-24 17:48
什么叫素数,除开1和本身,不能被其他数整除。
针对你的代码而言,下面这一行代码往上处理了什么数字,1, ...

经过各位老哥的热心解释,我已经基本勾勒出你们指导的原理
但你能用运算过程做一次我看看么

打比方 100 整除的是1, 2, 4, 5, 10, 20, 25, 50, 100

那么i * i >N 其实就判断到10 * 10 > 100,后面20 25 50 100也不判断了

也如3楼老哥说的,你们举例都是某数里面的因子来说这个,比如100里面因子或者256里面因子

那么现在我这个是 %  不是*

能用%的方式说一遍吗,谢谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-28 00:08:16 | 显示全部楼层
jcpython2 发表于 2022-10-27 16:11
经过各位老哥的热心解释,我已经基本勾勒出你们指导的原理
但你能用运算过程做一次我看看么

不明白你的问题

评分

参与人数 1荣誉 +1 鱼币 +1 收起 理由
jcpython2 + 1 + 1 感谢楼主无私奉献!

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-28 16:29:08 | 显示全部楼层
Stubborn 发表于 2022-10-24 17:48
什么叫素数,除开1和本身,不能被其他数整除。
针对你的代码而言,下面这一行代码往上处理了什么数字,1, ...

我所理解的你这段话是:判断100内是否能被整除只需要判断到10

因为100 除以1~10得出的数肯定少于100除以20~100的数,就因为后面的数除的值更少就不需要判断?为什么?

说回我的代码.

我的那行代码i * i是在判断素数途中,那么上面那个除一半就够,和这行代码有什么具体关系??

微信截图_20221028162754.png

老哥我基础是真的比较差,你可以不需要继续回答的,我感觉也是有点勉强
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-10-30 10:42:58 | 显示全部楼层
jcpython2 发表于 2022-10-28 16:29
我所理解的你这段话是:判断100内是否能被整除只需要判断到10

因为100 除以1~10得出的数肯定少于100除 ...

因为100 除以1~10得出的数肯定少于100除以20~100的数,就因为后面的数除的值更少就不需要判断?为什么?
回答:任意一个数字N,你看成 I * J = N(I>=J)
当J大于I的时候,出现什么情况?比如I=20,J=5,但是你在搜索的时候I=5这个结果就已经搜索过了。你不要觉得I=5,和I=20不一样,在这个过程这种,它们都代表一个情况,可以被整除。所以才说,超过一个临界值,就不需要再判断了。

上面那个除一半就够,和这行代码有什么具体关系??
是指步长吗?步长就是剔除偶数不计算在内
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-26 00:49

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表