| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4056 人关注过本帖
标题:VFP编程技巧擂台赛[一]
只看楼主 加入收藏
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
这么点数据量,跟配置没有关系,算法问题而已。

授人以渔,不授人以鱼。
2012-09-26 13:47
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:335
帖 子:9841
专家分:27213
注 册:2012-2-5
收藏
得分:0 
回复 51楼 TonyDeng
有什么好的算法,贡献出来吧

坚守VFP最后的阵地
2012-09-26 13:50
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:6 
把长字符串截取为短字符串,是正路。原始数据是放在外部文本文件中的,每次读一个单元,逐个单元分割处理,千万不要企图一次性处理整个文本。高效的算法代码量一定大,不要妄想有既不费代码又能高效的。守恒原理在任何事物上都有效,想要速度快,就得代码多、多耗内存,要么时间换空间,要么空间换时间,编程是平衡的艺术。

授人以渔,不授人以鱼。
2012-09-26 13:57
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:335
帖 子:9841
专家分:27213
注 册:2012-2-5
收藏
得分:0 
静僻
最近一段时间的摸索,确实是这个理

坚守VFP最后的阵地
2012-09-26 14:48
taohua300
Rank: 12Rank: 12Rank: 12
来 自:光
等 级:贵宾
威 望:14
帖 子:1636
专家分:3906
注 册:2009-3-11
收藏
得分:0 
单纯追求时间换空间或是空间换时间是得不偿失的
对于不同“量级”的目的
同样的两种算法,可能有的快有的慢
所以我认为不应该是通过某种算法去分配(平衡)时间和空间
而是分配(平衡)时间或空间去达到某种算法

下图
vfp中,for do while 比较
“量级”越大,两者差距越大
图片附件: 游客没有浏览图片的权限,请 登录注册

个性太多,无法显示
2012-09-26 15:04
taohua300
Rank: 12Rank: 12Rank: 12
来 自:光
等 级:贵宾
威 望:14
帖 子:1636
专家分:3906
注 册:2009-3-11
收藏
得分:0 
同样的目的在vs 2008下
100W次循环看不到差距
1000W次稍微有点差距,而同样的在vfp中,差距已经很大了
图片附件: 游客没有浏览图片的权限,请 登录注册
图片附件: 游客没有浏览图片的权限,请 登录注册
图片附件: 游客没有浏览图片的权限,请 登录注册

个性太多,无法显示
2012-09-26 15:07
taohua300
Rank: 12Rank: 12Rank: 12
来 自:光
等 级:贵宾
威 望:14
帖 子:1636
专家分:3906
注 册:2009-3-11
收藏
得分:0 
在vs 2008 c中,反而while 的效率要高


但把while循环中的
tt += j++;
改成
tt += j;
j++;
在循环 100W次的时候for的执行时间比while短

但是看后面两个反汇编后的代码
while 的执行效率肯定是比for高的

所以
如果是求前n项和,在c中n小于100W项,我用for
n > 1000W我用while

在vfp中我就用for

个性太多,无法显示
2012-09-26 15:14
taifu945
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:80
帖 子:1545
专家分:3298
注 册:2012-7-6
收藏
得分:6 
改进了程序,修复了28楼提到的对于某些汉字不能识别的问题。另外,如果字符串不以汉字结尾,且没有音标结束标志“]”的,那么,最后一个汉字后的所有字符全部被截掉,不会生成新记录。
程序代码:
**********************************************************
*  找出三个字段之间规律的算法:                          *
*  第一个字段,以“[”为界,用LEFT()函数取该界的左侧全部 *
*      当然,从第二条记录开始,该字段的左侧开始部位的取值*
*      应该以上一条记录的最后一个中文字为准;            *
*  第二个字段,很好分界,从“[”开始,到最近的第一个中文 *
*      字前面一个字符结束;                              *
*  第三个字段,从最近的第一个中文字开始,到最近的最后一个*
*      中文字结束。                                      *
**********************************************************
CLOSE ALL
SET DEFAULT TO C:\RR\Foxpro\
SET SAFETY OFF

Cstr=" how often[]肻多久一次 exercise['eks2saiz]v.&n.锻炼;运动 skateboard[]v.踩滑板;参加滑板运动 hardly['ha:dli]adv. 几乎不;几乎没有 ever['ev2]adv. 曾;曾经 shop[60p]v.购物 once[w3ns]adv. 一次 ABC"

IF !FILE("拆分字符串.DBF")
   CREATE TABLE 拆分字符串.DBF FREE ;
      (单词 C(15), 音标 C(20), 汉意 C(30))
ELSE
   USE 拆分字符串.DBF
   ZAP
ENDIF

STORE 1 TO 左边界, 右边界, 左中括号次数, 右中括号次数
字符串长度=LENC(Cstr)
右中括号个数=OCCURS("]",Cstr)
DO WHILE 右边界<字符串长度
   *********************
   *  取第一个字段内容  *
   *********************
   STORE "" TO 单词内容,音标内容,汉意内容
   左中括号位置=ATCC("[",Cstr,左中括号次数)
   右边界=左中括号位置-1
   FOR I=左边界 TO 右边界
      单词内容=单词内容+SUBSTRC(Cstr,I,1)
   NEXT

   *********************
   *  取第二个字段内容  *
   *********************
   左边界=左中括号位置
   右中括号位置=ATCC("]",Cstr,右中括号次数)
   右边界=右中括号位置+1
   DO WHILE 右边界<=字符串长度   &&查找汉字位置
      IF ASC(SUBSTRC(Cstr,右边界,1))>128
         右边界=右边界-1  &&第一个汉字的左边一位就是“音标”字段的结束
         EXIT
      ELSE
         右边界=右边界+1
      ENDIF
   ENDDO
   FOR I=左边界 TO 右边界
      音标内容=音标内容+SUBSTRC(Cstr,I,1)
   NEXT

   *********************
   *  取第三个字段内容  *
   *********************
   左边界=右边界+1
   右边界=左边界
   DO WHILE 右边界<=字符串长度   &&查找汉字位置
      IF ASC(SUBSTRC(Cstr,右边界,1))<129
         右边界=右边界-1  &&第一个非汉字的左边一位就是“汉意”字段的结束
         EXIT
      ELSE
         右边界=右边界+1
      ENDIF
   ENDDO
   FOR I=左边界 TO 右边界
      汉意内容=汉意内容+SUBSTRC(Cstr,I,1)
   NEXT
  

   *******************
   *  插入各字段内容  *
   *******************
   INSERT INTO 拆分字符串.DBF VALUES (LTRIM(单词内容),LTRIM(音标内容),LTRIM(汉意内容))

 


   ***************
   *  重置各位置  *
   ***************
   左边界=右边界+1
   左中括号次数=左中括号次数+1
   右中括号次数=右中括号次数+1
   IF 右中括号次数>右中括号个数
      EXIT
   ENDIF
ENDDO

CLOSE ALL
SET SAFETY OFF
RETURN

执行后的情况:
图片附件: 游客没有浏览图片的权限,请 登录注册

2012-09-26 16:47
taifu945
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:80
帖 子:1545
专家分:3298
注 册:2012-7-6
收藏
得分:0 
个人认为,现在的计算机硬件已经很高端了,程序编写时的清晰性应该摆在第一位,而不应该单纯考虑速度,使程序的可读性变差。否则,将来一旦需要维护,可是会要人命的。
2012-09-27 10:14
taifu945
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:80
帖 子:1545
专家分:3298
注 册:2012-7-6
收藏
得分:0 
以下是引用taohua300在2012-9-26 15:04:59的发言:

单纯追求时间换空间或是空间换时间是得不偿失的
对于不同“量级”的目的
同样的两种算法,可能有的快有的慢
所以我认为不应该是通过某种算法去分配(平衡)时间和空间
而是分配(平衡)时间或空间去达到某种算法

下图
vfp中,for do while 比较
“量级”越大,两者差距越大

我也用FoxPro 9.0测试了一下,同样是1000W次循环,在我的电脑上好象差别没那么大。对于代码我改了两处:1、把开始计时的时间放在更靠近循环头的地方;2、DO WHILE I<=10000000改为了DO WHILE I<10000001,这就大大提高了DO WHILE的循环速度。由此可见,小于等于和单纯的小于在运算时间上差别还是挺大的。经过这两处修改后,两者相差情况并不大。我连续运行了4次,以下是程序代码和运行结果的截图。
程序代码:
CLEAR
DECLARE LONG GetTickCount IN WIN32API

SS=0
Start=GetTickCount()
FOR I=1 TO 10000000
   SS=SS+1
NEXT
?"FOR 循环1000万次的时间为:"+STR(GetTickCount()-Start,5)+"毫秒"+CHR(13)+CHR(13) FONT "微软雅黑", 12

SS=0
I=1
Start=GetTickCount()
DO WHILE I<10000001
   SS=SS+1
   I=I+1
ENDDO
?"DO WHILE 循环1000万次的时间为:"+STR(GetTickCount()-Start,5)+"毫秒" FONT "微软雅黑", 12

CLEAR DLLS
RETURN

结果1:
图片附件: 游客没有浏览图片的权限,请 登录注册


结果2:
图片附件: 游客没有浏览图片的权限,请 登录注册


结果3:
图片附件: 游客没有浏览图片的权限,请 登录注册


结果4:
图片附件: 游客没有浏览图片的权限,请 登录注册



[ 本帖最后由 taifu945 于 2012-9-27 11:00 编辑 ]
2012-09-27 10:59
快速回复:VFP编程技巧擂台赛[一]
数据加载中...
 
   



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

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