数学中国

 找回密码
 注册
搜索
热搜: 活动 交友 discuz
楼主: 白新岭

[原创]请教vfbpgyfk先生一个编程问题

  [复制链接]
 楼主| 发表于 2020-11-26 15:41 | 显示全部楼层
CLEAR ALL
SELECT 1
USE D:\vfp温习\参考素数.DBF ALIAS 素数表
SELECT 2
USE D:\vfp温习\孪生素数对.DBF ALIAS 孪素表
    kssj=SECONDS()                      &&取出开始时间
   For N=1 to 100000
     @ 3,6 say N
            bpz=6*N+1
             Kf=INT(SQRT(bpz))       &&求出奇数的开方根
            SELECT  素数表             &&打开素数表
            LOCATE FOR 素数>=kf      &&根据开方根,查找最大素数
            DO CASE
                 CASE EOF()          &&如果超出素数表最后一条记录
                        GO BOTTOM
                 CASE 素数>kf     &&如果找到的素数比开方根值大,就将记录指针退回一个,保证使用的最大素数在开方根内
                        SKIP -1
             ENDCASE
             SSS=RECNO()    &&记录下最大素数(开方根内)记录位置(如果找到的素数等于开方根,则直接读取这个素数的位置)
            GO 1          &&从第一条记录开始读取素数(3)
              FOR j=1 TO SSS     &&内循环开始。这个循环实质上是从小到大顺序,依次读取素数。循环值是记录序号
                MZ=MOD(bpz,素数)   &&以读取的素数为条件,对被判断值求模 【qmz=MOD(bpz,素数)】文本号括着的原在此行语句体部分.特别需要注意的是在用标点符号时,一定改成英文模式及半角状态。
                IF MZ=0 OR MZ=2
                         EXIT         
                 ENDIF
                 SKIP            &&素数表指针向下移动一个
             ENDFOR
              IF j>sss
                 SELECT  孪素表      &&打开盛放素数的表
                APPEND BLANK                        &&增加一条空记录
                REPLACE 孪素 WITH bpz            &&将N值付给素数
              ENDIF
    endfor
    =MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")
这是筛选孪生素数对程序,在60万前不包括(3,5)这对,有5330对。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-11-26 16:02 | 显示全部楼层
* 以大定小选配素数对
LOCAL xjl,djl,ts,xss,dss,kssj,tj
CLEAR
SELECT 1
USE D:\vfp温习\不能被孪中合成数.DBF ALIAS 素数对    &&素数对表结构:偶数、统计
SELECT 2
USE D:\vfp温习\孪生素数对.DBF  ALIAS 素数表
kssj=SECONDS()
FOR i=2  to 10000
@ 3,6 say i
     n=i
        X=6*n+2
          Y=3*n+1  
        SELECT 素数表
        LOCATE FOR 孪素>X
         DO CASE
                 CASE EOF()
                         GO Bottom
                 CASE 孪素>X
                         SKIP -1
         ENDCASE
         xjl=1
         djl=RECNO()
         t=.T.
         DO WHILE t
                 dss=孪素
                GO xjl
                 xss=孪素
                                              &&放在这里比较合适,这里原来显示小素数的值,去掉了。
                IF xss<Y+1 OR dss>Y-1                              &&判断跳出语句如果放在后面,有时出现一个重复素数对
                          t=.T.
                           ELSE
                           t=.F.                                       &&跳出命令
                ENDIF                                               &&结束判断
                DO CASE
                         CASE xss+dss>X
                                 GO djl
                                 SKIP -1
                                 djl=RECNO()
                         CASE xss+dss=X
                                 EXIT
                         CASE xss+dss<X
                                 GO xjl
                                 SKIP
                                 xjl=RECNO()
                                 GO djl
                 ENDCASE
         ENDDO
         IF xss>Y OR dss<Y
         SELECT 素数对
                                APPEND BLANK
                                 REPLACE 偶数 WITH X
         ENDIF
ENDFOR
=MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")
这是筛选不能由孪中合成的数程序(用孪中+1代替,查找6n+2的数)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-11-26 20:08 | 显示全部楼层
CLEAR ALL
SELECT 1
USE D:\vfp温习\参考素数.DBF ALIAS 素数表
SELECT 2
USE D:\vfp温习\二生素数10.DBF ALIAS 二素表
    kssj=SECONDS()                      &&取出开始时间
   For N=1 to 25000
     @ 3,6 say N
     FOR  m=1 TO 4
            bpz=6*m+30*N+5
             Kf=INT(SQRT(bpz))       &&求出奇数的开方根
            SELECT  素数表             &&打开素数表
            LOCATE FOR 素数>=kf      &&根据开方根,查找最大素数
            DO CASE
                 CASE EOF()          &&如果超出素数表最后一条记录
                        GO BOTTOM
                 CASE 素数>kf     &&如果找到的素数比开方根值大,就将记录指针退回一个,保证使用的最大素数在开方根内
                        SKIP -1
             ENDCASE
             SSS=RECNO()    &&记录下最大素数(开方根内)记录位置(如果找到的素数等于开方根,则直接读取这个素数的位置)
            GO 1          &&从第一条记录开始读取素数(3)
              FOR j=1 TO SSS     &&内循环开始。这个循环实质上是从小到大顺序,依次读取素数。循环值是记录序号
                MZ=MOD(bpz,素数)   &&以读取的素数为条件,对被判断值求模 【qmz=MOD(bpz,素数)】文本号括着的原在此行语句体部分.特别需要注意的是在用标点符号时,一定改成英文模式及半角状态。
                IF MZ=0 OR  MOD(10,素数)=MOD(bpz,素数)
                         EXIT         
                 ENDIF
                 SKIP            &&素数表指针向下移动一个
             ENDFOR
              IF j>sss
                 SELECT 二素表      &&打开盛放素数的表
                APPEND BLANK                        &&增加一条空记录
                REPLACE 二素10 WITH bpz            &&将N值付给素数
              ENDIF
        ENDFOR
    ENDFOR
    =MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")
这是筛选二生素数d10的程序
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-11-27 10:28 | 显示全部楼层
SELECT 1
USE D:\vfp寻找素数式\素数式19.dbf ALIAS 素19
SELECT 2
USE D:\vfp寻找素数式\相同间距素数式类型普表升级.dbf ALIAS 同距式
kssj=SECONDS() &&取出开始时间
FOR I=1 TO 830000
@ 5,12 say I
    SELECT 1
    A=式19
    jl=RECNO() &&返回 记录号
      FOR J=1 TO 45
         SELECT 1
         SKIP
         B=式19
         C=B-A
         IF C>110
         EXIT
         ENDIF
         IF C=110 and J>22
            SELECT 1
            GO jl
            D=式19
            S=0
            M=0
            FOR E=1 TO J
            SELECT 1
            SKIP
            F=式19
            G=F-D
            S=S+G
            M=M+S
            SELECT 1
            SKIP
            endfor
          SELECT 2
          APPEND BLANK
          REPLACE 开头式值 WITH A
          REPLACE 开头记录 WITH jl
          REPLACE 跨过记录 WITH J
          REPLACE 二次累计和 WITH S
          REPLACE 二阶累计和 WITH M
          ENDIF
    endfor
    SELECT 1
    GO jl+1
ENDFOR
=MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")
这是升级版的,在至素数19的素数式中寻找最密素数式的各种类型。
还是不够完美,再升点级,虑去相同的素数式类型,只要监视一下二阶累计和就可以判断了,以前检查素数式是否过关时用过这样的方法,容易处理办到。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-11-27 11:21 | 显示全部楼层
本帖最后由 白新岭 于 2020-11-27 03:23 编辑

对于一个综合问题,我们要分步完成,先简单,再复杂,像梯子那样,逐步升高晋级,加大步骤,加多条件,这样处理问题比一步到位要容易的多。在这个过程,思路会越来越清楚,操作起来也比较顺手,相当于并程序,叠加程序,在这之前也需要像作文那样,先做伏笔,做上数据,以便后边程序利用。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-11-27 17:20 | 显示全部楼层
本帖最后由 白新岭 于 2020-12-3 02:01 编辑

SELECT 1
USE D:\vfp寻找素数式\素数式19.dbf ALIAS 素19
SELECT 2
USE D:\vfp寻找素数式\相同间距素数式类型普表升级1.dbf ALIAS 同距式
kssj=SECONDS() &&取出开始时间
     FOR jj=71  TO  80
SELECT 2
  go top
  PUBLIC AA
  AA=跨过记录
  AE=AA
  DO WHILE  eof()
       PUBLIC AD
       AD=跨过记录
       Aj=RECNO() &&返回 记录号
              IF AE<AD
                AE=AD
              ENDIF
          SELECT 1
          GO Aj+1
   ENDdo
FOR I=1 TO 830000
@ 5,12 say I
    SELECT 1
    A=式19
    jl=RECNO() &&返回 记录号
      FOR J=1 TO AE+10
         SELECT 1
         SKIP
         B=式19
         C=B-A
         IF C>2*jj
         EXIT
         ENDIF
         IF C=2*jj and J>AE-1
            SELECT 1
            GO jl
            D=式19
            S=0
            M=0
            FOR E=1 TO J
            SELECT 1
            SKIP
            F=式19
            G=F-D
            S=S+G
            M=M+S
            SELECT 1
            SKIP
            endfor
          SELECT 2
          APPEND BLANK
          REPLACE 开头式值 WITH A
          REPLACE 开头记录 WITH jl
          REPLACE 跨过记录 WITH J
          REPLACE 二次累计和 WITH S
          REPLACE 二阶累计和 WITH M
          ENDIF
    endfor
    SELECT 1
    GO jl+1
ENDFOR
  endfor
=MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")
虽然再次升级,可以连续计算,还是不太理想。
此程序在查找最大值时出了错。你能看出来吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-11-28 10:55 | 显示全部楼层
本帖最后由 白新岭 于 2020-12-3 02:03 编辑

SELECT 1
USE D:\vfp寻找素数式\素数式19.dbf ALIAS 素19
SELECT 2
USE D:\vfp寻找素数式\相同间距素数式类型普表升级11.dbf ALIAS 同距式
kssj=SECONDS() &&取出开始时间
     FOR jj=81  TO  82
SELECT 2
  go top
  PUBLIC AA
  AA=跨过记录
  AE=AA
  DO WHILE  eof()
       PUBLIC AD
       AD=跨过记录
       Aj=RECNO() &&返回 记录号
              IF AE<AD
                AE=AD
              ENDIF
          SELECT 1
          GO Aj+1
   ENDdo
FOR I=1 TO 830000
@ 5,12 say I
    SELECT 1
    A=式19
    jl=RECNO() &&返回 记录号
    @ 10,24 say jl
      FOR J=1 TO AE+10
         SELECT 1
         SKIP
         B=式19
         C=B-A
         IF C>2*jj
         EXIT
         ENDIF
         IF C=2*jj and J>AE-1
            SELECT 1
            GO jl
            D=式19
            S=0
            M=0
            FOR E=1 TO J
            SELECT 1
            SKIP
            F=式19
            G=F-D
            S=S+G
            M=M+S
            SELECT 1
            SKIP
            ENDFOR
           SELECT 2
           count all for M=二阶累计和 to js
               IF js=0
               SELECT 2
               APPEND BLANK
               REPLACE 开头式值 WITH A
               REPLACE 开头记录 WITH jl
               REPLACE 跨过记录 WITH J
               REPLACE 二次累计和 WITH S
               REPLACE 二阶累计和 WITH M
               REPLACE 跨度总值 WITH C
               endif
          ENDIF
    endfor
    SELECT 1
    GO jl+1
ENDFOR
  endfor
=MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")
这个程序基本上能完成一套连贯k生素数式问题。
这个终极版本是在解决重复问题后发出的,在最后一笔问题的处理上,还是有点疑问,刚刚开始时,我把上下判断条件分开了,所以程序提示找不到变量M,M是局部变量,如果把endif提前,放在下一个条件之下,局部变量M就不存在了,实际上,最后的条件语句是嵌套,即在上一个条件的基础上。困扰我的这个问题解决。
还有一个问题,程序有时提示已到表尾,所以我加了显示指针(即所在记录条位置),看运行,的确是这样,指针一直下移,在主循环进入下一个值时,指针没有返回第一条记录。所以,要简单处理一下,即加条调回指针的语句,让指针返回到第一条记录上,在主循环下一次循环开始前。
与上楼犯得同样毛病。一下各楼也可能有错误,不再一一提示了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-11-28 19:38 | 显示全部楼层
素数式可以以任何方式打断其链条,指用0开头,然后统一减一个定值打断它,所有素数都去它的减值。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-11-29 16:05 | 显示全部楼层
CLEAR ALL
SELECT 1
USE D:\vfp温习\等差三生素元数30.DBF ALIAS 三素元表
    kssj=SECONDS()                      &&取出开始时间
   For N=61 to 269 STEP 2
     @ 3,6 say N
            bpz=N
                IF  MOD(N,3)=0 OR MOD(N,5)=0 OR MOD(N,7)=0 OR MOD(N,7)=2 OR MOD(N,7)=4
                  else
                 SELECT 1      &&打开盛放素数的表
                APPEND BLANK                        &&增加一条空记录
                REPLACE 三素元 WITH bpz            &&将N值付给素数
              ENDIF
    ENDFOR
    =MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")
这是筛选等差三生素数d30的生成元程序。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-11-29 17:16 | 显示全部楼层
CLEAR ALL
SELECT 1
USE D:\vfp温习\参考素数.DBF ALIAS 素数表
SELECT 2
USE D:\vfp温习\等差三生素元数30.DBF ALIAS 三素数元
SELECT 3
USE D:\vfp温习\等差三生素数30.DBF ALIAS 三素表
    kssj=SECONDS()                      &&取出开始时间
   For N=1 to 10000
     @ 3,6 say N
         SELECT 2
        go 1
         DO WHILE NOT EOF()
            bpz=三素元+(N-1)*210
             Kf=INT(SQRT(bpz))       &&求出奇数的开方根
            SELECT  素数表             &&打开素数表
            LOCATE FOR 素数>=kf      &&根据开方根,查找最大素数
            DO CASE
                 CASE EOF()          &&如果超出素数表最后一条记录
                        GO BOTTOM
                 CASE 素数>kf     &&如果找到的素数比开方根值大,就将记录指针退回一个,保证使用的最大素数在开方根内
                        SKIP -1
             ENDCASE
             SSS=RECNO()    &&记录下最大素数(开方根内)记录位置(如果找到的素数等于开方根,则直接读取这个素数的位置)
            GO 4          &&从第一条记录开始读取素数(3)
              FOR j=1 TO SSS-3     &&内循环开始。这个循环实质上是从小到大顺序,依次读取素数。循环值是记录序号
                MZ=MOD(bpz,素数)   &&以读取的素数为条件,对被判断值求模 【qmz=MOD(bpz,素数)】文本号括着的原在此行语句体部分.特别需要注意的是在用标点符号时,一定改成英文模式及半角状态。
                IF MZ=0 OR MZ=MOD(30,素数) OR MZ=MOD(60,素数)
                         EXIT         
                 ENDIF
                 SKIP            &&素数表指针向下移动一个
                ENDFOR
              IF j>sss-3
                 SELECT  三素表      &&打开盛放素数的表
                APPEND BLANK                        &&增加一条空记录
                REPLACE 三素30 WITH bpz            &&将N值付给素数
            ENDIF
          SELECT  三素数元
        skip
        ENDDO
    endfor
    =MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")
这是筛选等差3生素数d30程序
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|手机版|小黑屋|数学中国 ( 京ICP备05040119号 )

GMT+8, 2024-5-2 06:47 , Processed in 0.077149 second(s), 15 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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