数学中国

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

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

  [复制链接]
 楼主| 发表于 2019-3-29 10:51 | 显示全部楼层
今天在台式电脑上运算同样的数据要比笔记本上快的多,而且台式的才4G内存,而笔记本是8G内存,4个处理器,不知这是问什么。
 楼主| 发表于 2019-3-30 18:03 | 显示全部楼层
* 以大定小选配素数对
LOCAL xjl,djl,ts,xss,dss,zjd,kssj
CLEAR
SELECT 1
USE F:\MYVFP\学习VFP\素数对.DBF EXCL ALIAS 素数对             &&素数对表结构:偶数、小素数、大素数
IF RECCOUNT()>0
        ??CHR(7)
        ts=MESSAGEBOX("清空“素数对”表吗?",4+48+256,"提示窗口")
        IF ts=6
                ZAP
        ENDIF
ENDIF
SELECT 2
USE F:\MYVFP\学习VFP\新制素数表.DBF EXCL ALIAS 素数表
INPUT "请输入循环的开始值 ksz= " TO ksz                    &&如果是求单个偶数的素数对,开始值等于结束值即可
INPUT "请输入循环的结束值 jsz= " TO jsz
kssj=SECONDS()
FOR i=ksz TO jsz  &&显然循环没有加步长值,应该加 step 2 这样可以保证不循环奇数值
        zjd=i/2
        LOCATE FOR 素数>=i  &&这里i代表偶数
        DO CASE
                CASE EOF()
                        GO Bottom
                CASE 素数>i
                        SKIP -1
        ENDCASE
        xjl=1  &&小素数的位置                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
        djl=RECNO()  &&大素数的位置
        DO WHILE .T. &&如果条件为真
                dss=素数  &&把素数赋给大素数
                GO xjl    &&到小素数的位置
                xss=素数  &&把素数赋给小素数
                @ 10,10 SAY xss     &&显示小素数    &&放在这里比较合适
                IF xss>zjd OR dss<zjd                               &&判断跳出语句如果放在后面,有时出现一个重复素数对
                        EXIT                                            &&跳出命令
                ENDIF                                               &&结束判断
                DO CASE
                        CASE xss+dss>i  &&小素数+大素数如果大于偶数
                                GO djl  &&定位到大素数的起始位置
                                SKIP -1  &&向上移动一个
                                djl=RECNO()  &&从新记住大素数的位置
                        CASE xss+dss=i   &&不知道问什么这时的大素数已经变成了新的记录条所对应的素数,还是分之语句的问题,当正好是偶数时,做一下工作
                                SELECT 素数对  &&选择素数对表
                                APPEND BLANK   &&增加一条空记录
                                REPLACE 偶数 WITH i  &&把i付给偶数
                                REPLACE 小素数 WITH xss  &&把小素数赋给小素数
                                REPLACE 大素数 WITH dss  &&把大素数赋给大素数
                                SELECT 素数表  &&选择素数表
                                GO xjl  &&定位到小素数的起始位置
                                SKIP  &&下移一条记录
                                xjl=RECNO()  &&从新记住小素数的位置
                                GO djl  &&把指针移动到大素数的起始位置
                                SKIP -1 &&向上移动一条记录
                                djl=RECNO() &&从新记住大素数的位置
                        CASE xss+dss<i  &&如果素数之和小于偶数
                                GO xjl  &&把指针移动到小素数的位置
                                SKIP  &&向下移动一条记录
                                xjl=RECNO() &&从新记住小素数的位置
                                GO djl &&到大素数的位置
                ENDCASE  &&结束分支循环语句
        ENDDO  &&结束中层循环
ENDFOR  &&结束最外层循环 。从整个程序看就是缺少步长
=MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")
CLOSE ALL
这是多年以前那宝吉编的 求偶数素数对的程序(大部分加了注解)
 楼主| 发表于 2019-4-20 09:09 | 显示全部楼层
CLEAR ALL
SELECT 1
USE f:\visualfoxpro项目\四生素数表.DBF ALIAS 四素表
SELECT 2
USE f:\visualfoxpro项目\四素合成统计.DBF ALIAS 四生合成结果
SELECT 3
USE f:\visualfoxpro项目\四生素数合成参照表.DBF ALIAS 参照表
    kssj=SECONDS()                      &&取出开始时间
   For N=600001 to 620000
    @ 3,6 say N
    SELECT 参照表
    go 1
         FOR M=1 TO 5
          @ 4,8 say 四合元
          X=四合元+(N-1)*210
          Y=X/2
                zhz=Y      &&求出偶数的中值
                SELECT  四素表             &&打开三素数表
                LOCATE FOR 四素>=zhz      &&根据三素表,查找最大三素数
                DO CASE
                CASE EOF()          &&如果超出三素数表最后一条记录
                        GO BOTTOM
                CASE 四素>zhz   &&如果找到三的素数中值大,就将记录指针退回一个,保证使用的最大三素数在中值内,小于等于即
                        SKIP -1
                       ENDCASE
                SSS=RECNO()+1   &&记录下最大三素数(中值内)记录位置(如果找到的素数等于开方根,则直接读取这个素数的位置)
                 LOCATE FOR 四素>=X     &&根据三素表,查找最大三素数
                DO CASE
                CASE EOF()          &&如果超出三素数表最后一条记录
                        GO BOTTOM
                CASE 四素>X   &&如果找到三的素数中值大,就将记录指针退回一个,保证使用的最大三素数在中值内,小于等于即
                        SKIP -1
                       ENDCASE
                SSSX=RECNO()+1   &&记录下最大三素数(中值内)记录位置(如果找到的素数等于开方根,则直接读取这个素数的位置)
                  GO 1           &&从第一条记录开始读取三素数
                  FOR J=1 TO SSS      &&内循环开始。这个循环实质上是从小到大顺序,依次读取素数。循环值是记录序号
                     I=J
                     Z=X-四素 &&以读取的三素数为条件,对X-三素数值进行判断,看一看是否在三生素数表内
                       go SSSX-2-J
                       count next INT((2*SSS-SSSX)*2.1) for Z=四素 to js
                        IF js>0
                         EXIT         
                        ENDIF
                       GO I+1         &&素数表指针向下移动一个
                  ENDFOR
                   IF j>SSS
                   SELECT 四生合成结果             &&打开盛放素数的表
                   APPEND BLANK                    &&增加一条空记录
                   REPLACE 合成数 WITH X       &&将N值付给素数
                   ENDIF
                  SELECT 参照表
                  SKIP
       ENDFOR
     ENDFOR
   =MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")   
    CLEAR ALL
这是用计数函数寻找那些不能有四生素数合成的偶数,比查找函数快,但是比以大定小的素数配对要慢。
 楼主| 发表于 2019-4-20 09:11 | 显示全部楼层
* 以大定小选配素数对
LOCAL xjl,djl,ts,xss,dss,kssj,tj
CLEAR
SELECT 1
USE F:\visualfoxpro项目\四生素数对.DBF ALIAS 素数对    &&素数对表结构:偶数、统计
IF RECCOUNT()>0
        ??CHR(7)
        ts=MESSAGEBOX("清空“素数对”表吗?",4+48+256,"提示窗口")
        IF ts=6
                ZAP
        ENDIF
ENDIF
SELECT 2
USE F:\visualfoxpro项目\四生素数表.DBF EXCL ALIAS 素数表
SELECT 3
USE f:\visualfoxpro项目\四生素数合成参照表.DBF ALIAS 参照表
kssj=SECONDS()
for n=620001  to 720000
@ 3,6 say n
SELECT 参照表
    go 1
         FOR M=1 TO 5
          @ 4,8 say 四合元
          X=四合元+(n-1)*210
          Y=X/2   &&求出偶数的中值
        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=四素
                @ 10,10 SAY xss                                     &&放在这里比较合适
                IF xss<Y OR dss>Y                              &&判断跳出语句如果放在后面,有时出现一个重复素数对
                          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
         SELECT 参照表
         skip
ENDFOR
ENDFOR
=MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")
CLOSE ALL
这是以大定小素数配对程序,它是运算最快的,没有更好的方法再继续提高运算速度了。
 楼主| 发表于 2019-4-24 09:46 | 显示全部楼层
CLEAR ALL
SELECT 1
USE f:\visualfoxpro项目\四生素数表.DBF ALIAS 四素表
SELECT 2
USE f:\visualfoxpro项目\四素合成统计.DBF ALIAS 四生合成结果
SELECT 3
USE f:\visualfoxpro项目\四生素数合成参照表.DBF ALIAS 参照表
    kssj=SECONDS()                      &&取出开始时间
   For N=600001 to 620000
    @ 3,6 say N
    SELECT 参照表
    go 1
         FOR M=1 TO 5
          @ 4,8 say 四合元
          X=四合元+(N-1)*210
          Y=X/2
                zhz=Y      &&求出偶数的中值
                SELECT  四素表             &&打开三素数表
                LOCATE FOR 四素>=zhz      &&根据三素表,查找最大三素数
                DO CASE
                CASE EOF()          &&如果超出三素数表最后一条记录
                        GO BOTTOM
                CASE 四素>zhz   &&如果找到三的素数中值大,就将记录指针退回一个,保证使用的最大三素数在中值内,小于等于即
                        SKIP -1
                       ENDCASE
                SSS=RECNO()+1   &&记录下最大三素数(中值内)记录位置(如果找到的素数等于开方根,则直接读取这个素数的位置)
                 LOCATE FOR 四素>=X     &&根据三素表,查找最大三素数
                DO CASE
                CASE EOF()          &&如果超出三素数表最后一条记录
                        GO BOTTOM
                CASE 四素>X   &&如果找到三的素数中值大,就将记录指针退回一个,保证使用的最大三素数在中值内,小于等于即
                        SKIP -1
                       ENDCASE
                SSSX=RECNO()+1   &&记录下最大三素数(中值内)记录位置(如果找到的素数等于开方根,则直接读取这个素数的位置)
                  GO 1           &&从第一条记录开始读取三素数
                  FOR J=1 TO SSS      &&内循环开始。这个循环实质上是从小到大顺序,依次读取素数。循环值是记录序号
                     I=J
                     Z=X-四素 &&以读取的三素数为条件,对X-三素数值进行判断,看一看是否在三生素数表内
                       go SSSX-2-J
                       count next INT((2*SSS-SSSX)*2.1) for Z=四素 to js
                        IF js>0
                         EXIT         
                        ENDIF
                       GO I+1         &&素数表指针向下移动一个
                  ENDFOR
                   IF j>SSS
                   SELECT 四生合成结果             &&打开盛放素数的表
                   APPEND BLANK                    &&增加一条空记录
                   REPLACE 合成数 WITH X       &&将N值付给素数
                   ENDIF
                  SELECT 参照表
                  SKIP
       ENDFOR
     ENDFOR
   =MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")   
    CLEAR ALL
 楼主| 发表于 2019-4-27 08:42 | 显示全部楼层
CLEAR ALL
SELECT 1
USE c:\visualfoxpro项目\s3165万内素数.DBF ALIAS 素数表
SELECT 2
USE c:\visualfoxpro项目\四生素数生成元.DBF ALIAS 四生成元
SELECT 3
USE c:\visualfoxpro项目\四生素数表.DBF ALIAS 四素表
    kssj=SECONDS()                      &&取出开始时间
   For N=12 to 13
    @ 3,6 say N
        SELECT 四生成元
        go 1
        DO WHILE NOT EOF()
        @ 2,5 say  四生元
            bpz=四生元+(N-1)*223092870
            Kf=INT(SQRT(bpz))       &&求出奇数的开方根
            SELECT  素数表             &&打开素数表
            LOCATE FOR 素数>=kf      &&根据开方根,查找最大素数
            DO CASE
                CASE EOF()          &&如果超出素数表最后一条记录
                        GO BOTTOM
                CASE 素数>kf     &&如果找到的素数比开方根值大,就将记录指针退回一个,保证使用的最大素数在开方根内
                        SKIP -1
            ENDCASE
            SSS=RECNO()    &&记录下最大素数(开方根内)记录位置(如果找到的素数等于开方根,则直接读取这个素数的位置)
            GO 9           &&从第一条记录开始读取素数(3)
             FOR j=1 TO SSS-8      &&内循环开始。这个循环实质上是从小到大顺序,依次读取素数。循环值是记录序号
                MZ=MOD(bpz,素数)   &&以读取的素数为条件,对被判断值求模 【qmz=MOD(bpz,素数)】文本号括着的原在此行语句体部分.特别需要注意的是在用标点符号时,一定改成英文模式及半角状态。
                IF MZ=0 OR MZ=2 OR MZ=6 OR MZ=8
                        EXIT         
                ENDIF
                SKIP            &&素数表指针向下移动一个
             ENDFOR
             IF j>sss-8
                SELECT  四素表      &&打开盛放素数的表
                APPEND BLANK                        &&增加一条空记录
                REPLACE 四素 WITH bpz            &&将N值付给素数
            ENDIF
         SELECT  四生成元
        skip
       ENDDO
   endfor
   =MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")
 楼主| 发表于 2019-6-1 18:28 | 显示全部楼层
本帖最后由 白新岭 于 2019-6-1 14:16 编辑

如果把程序中的显示命令注销后,程序比以前运行速度快的多,窗口中的显示,可以通过工具栏中的选项----显示---把复选框(状态栏)中的对勾去掉,不知道是否会提高运算速度否?,计算100万内的划分段中1万的数据用时7小时25分钟,明天同样计算一下,看一看提高多少。
第二个区段也算完了,用时553分5.4秒
第三个区段用时628分53.75秒
第四个区段用时679分26.43秒
第五个区段用时689分7.23秒
第九个区段用时708分36.08秒
第六个区段用时725分1.13秒
第七个区段用时726分11.49秒(六和七的时间可能弄反了)
第八个区段用时727分32.24秒
第十个区段用时728分22.57秒(后边的程序用时与开着多个工作区间不一样)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-6-2 11:53 | 显示全部楼层
今天把工具栏中---选项---显示中的状态栏复选勾去掉了,可是程序运行后,主窗口,出现了滚动数据,更多了,没有验证运行速度的快慢。我不知道是否有办法去掉一切不必要的显示功能,这样可以提高运算速度。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-6-2 12:06 | 显示全部楼层
我现在打开了另一个程序来验证提高速度的效果,不可思议的是运算2000个外循环只用了2分15.33秒,如果按比例计算,只需用2分15.33秒*5=11分17.45秒就可以完成1万个数据的处理,比起7小时25分钟的来说,那简直太快了,我们拭目以待,等待实验结果。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-6-2 12:11 | 显示全部楼层
把工具----选项------显示----中的“状态栏”,“命令结果”,“系统信息”,前的对勾都去掉就可以了。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-25 06:02 , Processed in 0.087890 second(s), 15 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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