标题:用删除法编写一个制作素数表的vfp程序
只看楼主
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
以下是引用独木星空在2021-9-16 05:47:09的发言:

所以能建立分段运算是关键,把任务划分,分段运算,一次性运算无论是内存,还是运行时间都不允许。

用那种方法应该都可以分次、分段进行,只是算法不同。

[此贴子已经被作者于2021-9-16 09:31编辑过]

2021-09-16 09:29
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
以下是引用独木星空在2021-9-16 05:47:09的发言:

还有一个有利条件,可以同时打开4个程序运行(再多也不行,因为此时8GB内存几乎全部占用)。

用多进程分配任务来处理是可以,进程间协同处理同一个表数据。能同时打开进程的个数应该不只4个,VFP的进程占内存不算多,通常就几M,顶多也就10几M。至于DBF文件处理是通过缓冲与磁盘交换来处理,占实际内存也不会太多。
2021-09-16 09:42
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
以下是引用独木星空在2021-9-16 05:47:09的发言:

我所设计的,速度慢,关键就是数据的存储,读取上浪费了时间,能不能把一个外循环批次的数据用数组调入内存,然后对内存变量进行处理,意即调入是都为真,然后开始调入参考素数表中的素数,对它们进行从新设置,把整除的标记为假,处理完毕。把还是真的存盘,完成本次操作,进入下一个外循环即可。

用数组分块处理好再将数组整块写入表速度肯定比逐个数据直接读写表快。
另外,算法也很重要,如:
Kf=INT(SQRT(bpz))                   &&求出被判断值的开方根
SELECT 2
GO 1
COUNT ALL FOR 素数<=kf TO jlh  &&借用原来的记录号,实际上统计kf以前的素数个数

素数<=kf 即 素数<=INT(SQRT(bpz))
开方运算应该比乘方运行慢,尤其是数值较大时更慢,可试改为:
(素数*素数)<=bpz
另,在循环体内尽量避免使用扫描整个表的语句,如:
COUNT ALL FOR 素数<=kf TO jlh  &&借用原来的记录号,实际上统计kf以前的素数个数
这样当表记录越来越多时,运行速度就越慢,尤其是循环次数多时更慢。


[此贴子已经被作者于2021-9-16 10:21编辑过]

2021-09-16 10:13
独木星空
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:河北省曲阳县
等 级:版主
威 望:57
帖 子:713
专家分:556
注 册:2016-6-29
得分:0 
回复 59楼 laowan001
select 列名 from 表名

用那句代替后,不是提示表别名已被占用,就是找不到列"素数式"
不知道为何?

素数问题的解决是我学习编程永恒的动力。
2021-09-16 10:22
独木星空
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:河北省曲阳县
等 级:版主
威 望:57
帖 子:713
专家分:556
注 册:2016-6-29
得分:0 
回复 70楼 laowan001
能想到的也就这两种情况。

素数问题的解决是我学习编程永恒的动力。
2021-09-16 10:27
独木星空
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:河北省曲阳县
等 级:版主
威 望:57
帖 子:713
专家分:556
注 册:2016-6-29
得分:0 
回复 45楼 laowan001
CLEAR
SELECT 1
USE D:\标记法\数据源表.DBF ALIAS 数据源
SELECT 2
USE D:\标记法\素数表5万.DBF ALIAS 素数表参
SELECT 3
USE D:\标记法\数据表a.DBF ALIAS 数据a
SELECT 5
USE D:\标记法\素数表结果1.DBF ALIAS 素数表果
kssj=SECONDS()                     
FOR i=11 TO 12
   @12,10 SAY i
   SELECT 3
   DELETE ALL &&因为此表将写入新的数据,所以提前清空数据,即记录条值
   PACK
   SELECT 1
   GO 1
   FOR j=1 TO 1658880
   sss=素数式
   dclz=sss+(i-1)*9699690  &&dclz是待处理值
   SELECT 3
   APPEND BLANK
   REPLACE 数据1 WITH dclz
   SELECT 1
   SKIP
   ENDFOR
      SELECT 3
      GO 1658880
      bpz=数据1
      Kf=INT(SQRT(bpz))
      GO 1
      SELECT 2
      GO 1
      COUNT ALL FOR 素参<=kf TO jlh  && jlh=RECNO()
      xhcs=jlh-8 &&xhcs是循环次数的简写(第一个字母代替)
      SELECT 2   
      GO 9
        FOR k=1 TO xhcs
         sc=素参
            SELECT 3
            jlts1=RECCOUNT()  &&把数据a表中的记录条总数赋给变量:jlts1
            GO 1
            FOR h1=1  to jlts1
            sj1=数据1
            ys1=MOD(sj1,sc)
            IF ys1=0
            SELECT 3
            DELETE next 1
            ENDIF
            SELECT 3
            SKIP
            ENDFOR
            SELECT 3
            PACK
        SELECT 2
        skip  
        ENDFOR
      
       INSERT INTO 素数表果 (素数) SELECT 数据1 FROM 数据a
 ENDFOR
 =MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")   计算11,12两个区间用时27分58:53秒
这次只是把存表部分改动了一下(即程序最后部分),开始部分没有修改成功,不是别名被占用,就是找不到列“素数式”(英文符号单引号)。
主要循环体还没有用数组代替在内存中运算(或许这是提速的关键)。

素数问题的解决是我学习编程永恒的动力。
2021-09-16 12:42
laowan001
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:54
帖 子:802
专家分:1914
注 册:2015-12-30
得分:0 
回复 76楼 独木星空
最开始加上  close database
2021-09-16 13:42
独木星空
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:河北省曲阳县
等 级:版主
威 望:57
帖 子:713
专家分:556
注 册:2016-6-29
得分:0 
回复 59楼 laowan001
SELECT 素数式+(i-1)*9699690 数据1 FROM 数据源 INTO CURSOR 数据a READWRITE
用此语句代替后,一直也不能正常运行(包括关闭数据,无论放到什么位置),不是提示别名被占用,就是找不到列“素数式”,后来还出现其他对话框(定位表文件,选择定位数据源不正确,选择定位数据a不正确,二者应选其一,那个也不正确)。
最后把别名改成了表原名,可以了,不再有其他提示,不过第一步就说超出记录范围,干脆把go 1658880去掉,直接用i*9699690代替最大开方值,只进行了一步,go 1也超出记录范围,啊?,数据a里边没有任何记录条。
所以我怀疑那条语句并没有把数据源中的值+(i-1)*9699690后改写到数据a中。

素数问题的解决是我学习编程永恒的动力。
2021-09-16 15:41
laowan001
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:54
帖 子:802
专家分:1914
注 册:2015-12-30
得分:0 
use 数据源
brow
看下有没有字段:素数式,如果没有的话,或者改表中的字段名,或者改你的程序
这种基本错误应该会排查了

程序开始估计还是没加 close database,否则不会出现“别名被占用”
2021-09-16 15:52
独木星空
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:河北省曲阳县
等 级:版主
威 望:57
帖 子:713
专家分:556
注 册:2016-6-29
得分:0 
回复 59楼 laowan001
CLEAR
close database
SELECT 1
USE D:\标记法\数据源表.DBF ALIAS 数据源A
SELECT 2
USE D:\标记法\素数表5万.DBF ALIAS 素数表参
SELECT 3
USE D:\标记法\数据表a.DBF ALIAS 数据A
SELECT 5
USE D:\标记法\素数表结果.DBF ALIAS 素数表果
kssj=SECONDS()                     
FOR i=11 TO 12
   @12,10 SAY i
       SELECT 3
       DELETE ALL &&因为此表将写入新的数据,所以提前清空数据,即记录条值
       PACK
      INSERT INTO 数据A (数据1) SELECT 素数式+(i-1)*9699690 FROM 数据源A && 素数式+(i-1)*9699690 数据1 FROM  数据源表 INTO CURSOR 数据表a READWRITE  &&select list item 选择列表项,之前它不管,[ ,...]应该是字段名用逗号隔开
      SELECT 3
      bpz=i*9699690
      Kf=INT(SQRT(bpz))
      GO 1
      SELECT 2
      GO 1
      COUNT ALL FOR 素参<=kf TO jlh  && jlh=RECNO()
      xhcs=jlh-8 &&xhcs是循环次数的简写(第一个字母代替)
      SELECT 2   
      GO 9
        FOR k=1 TO xhcs
         sc=素参
            SELECT 3
            jlts1=RECCOUNT()  &&把数据a表中的记录条总数赋给变量:jlts1
            GO 1
            FOR h1=1  to jlts1
            sj1=数据1
            ys1=MOD(sj1,sc)
            IF ys1=0
            SELECT 3
            DELETE next 1
            ENDIF
            SELECT 3
            SKIP
            ENDFOR
            SELECT 3
            PACK
        SELECT 2
        skip  
        ENDFOR
      
            SELECT 3
            jlts2=RECCOUNT()  &&把数据a表中的记录条总数赋给变量:jlts1
            GO 1
            FOR h2=1  to jlts2
            sj2=数据1
            SELECT 5
            APPEND BLANK
            REPLACE 素数 WITH sj2
            SELECT 3
            SKIP
            ENDFOR
 ENDFOR
 =MESSAGEBOX("运行时间:"+LTRIM(STR(INT((SECONDS()-kssj)/60)))+"分"+LTRIM(STR(MOD(SECONDS()-kssj,60),5,2))+"秒",64,"运行时间提示")
那个语句无法应用,把那部分用最后的语句,改写了下,能正常运行,用时28分27:93秒,也不知道时间是否减少了。

素数问题的解决是我学习编程永恒的动力。
2021-09-16 16:04



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-506838-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.022794 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved