[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
终于将效率问题解决了,但代码确实难读了。。。
说明一下:先计算出文本的总行数,然后用渐近法计算出第一个日期(先算年再算月和日)
,然后再用for在按行读取数据时进行日期的累加和输出到新文本。
  1. @echo off&setlocal enabledelayedexpansion
  2. set "t=%time%"&echo.>c.txt
  3. rem 提出当前的年月日数值
  4. set /a year=%date:~,4%,month=1%date:~5,2%%%100,day=1%date:~8,2%%%100
  5. rem 设置变量
  6. for %%i in (31 29 31 30 31 30 31 31 30 31 30 31) do (
  7.     set /a num+=1&set "_!num!=%%i"
  8.     set "code1=!code1! %%i"&set "code2=!code2! !num!#%%i"
  9. )
  10. rem 获取文本总行数
  11. for /f "usebackq delims=" %%i in ("ab cd.txt") do set /a n+=1
  12. rem 计算并减去本年已过的天数
  13. set /a n=n-day
  14. for %%a in (%code1%) do (
  15.     if "!m!" neq "%month%" (
  16.        set /a n-=%%a,m+=1
  17.        ) else (
  18.        goto lp1
  19.    )
  20. )
  21. :lp1
  22. rem 计算初始年份
  23. set /a year-=1,n-=365
  24. set /a a=year%%4,b=year%%100,c=year%%400,yun=28,_2=28
  25. if %b% equ 0 (
  26.    if %c% equ 0 set /a n-=1,yun+=1,_2+=1
  27.    ) else (
  28.    if %a% equ 0 set /a n-=1,yun+=1,_2+=1
  29. )
  30. if %n% geq 0 goto lp1
  31. set "code1=!code1:29=%yun%!"&set "code2=!code2:29=%yun%!"
  32. rem 计算初始月份和日期
  33. for %%a in (%code2%) do (
  34.     for /f "tokens=1,2 delims=#" %%i in ("%%a") do (
  35.         set /a n+=%%j
  36.         if !n! geq 0 set /a month=%%i-1,day=%%j-n&goto next
  37.     )
  38. )
  39. :next
  40. rem 核心代码部分,读取文本内容并递加日期,输出到新文本
  41. for /f "usebackq delims=" %%i in ("ab cd.txt") do (
  42.     set /a n=day-_!month!
  43.     if !n! gtr 0 call :lp2
  44.     if !month! geq 10 (
  45.        if !day! geq 10 (
  46.           echo !year!年!month!月!day!日 %%i>>c.txt
  47.           ) else (
  48.           echo !year!年!month!月0!day!日 %%i>>c.txt
  49.        )
  50.        ) else (
  51.        if !day! geq 10 (
  52.           echo !year!年0!month!月!day!日 %%i>>c.txt
  53.           ) else (
  54.           echo !year!年0!month!月0!day!日 %%i>>c.txt
  55.        )
  56.     )
  57.     set /a day+=1
  58. )
  59. echo 开始时间:%t%
  60. echo 结束时间:%time%
  61. pause>nul&goto :eof
  62. :lp2
  63. rem 子程序:跨月、跨年的计算和判断
  64. echo.>>c.txt
  65. set /a month+=1,day=1
  66. if %month% equ 13 (
  67.    set /a year+=1,month=1,a=year%%4,b=year%%100,c=year%%400,_2=28
  68.    if !b! equ 0 (
  69.       if !c! equ 0 set "_2=29"
  70.       ) else (
  71.       if !a! equ 0 set "_2=29"
  72.    )
  73. )
复制代码

[ 本帖最后由 batman 于 2008-10-20 03:40 编辑 ]
***共同提高***

TOP

呵呵,对效率的考验。。
各位都出了精彩的代码了。
暂时没时间细看代码,下回去慢慢看。。。
初步做了下测试。


16楼 batman 耗时 0 小时 1 分钟 5 秒 31 毫秒

14楼 rat 耗时 0 小时 0 分钟 57 秒 40 毫秒

12楼 terse 耗时 0 小时 1 分钟 7 秒 75 毫秒

本人目前的代码 耗时: 0 小时 0 分钟 13 秒 72 毫秒
代码在U盘,下次发出来。

其实思路很简单,先获取总行数,并得到N 天前的日期。再逐日递加日期。
技术问题请到论坛发帖求助!

TOP

原帖由 随风 于 2008-10-20 15:09 发表
呵呵,对效率的考验。。
各位都出了精彩的代码了。
暂时没时间细看代码,下回去慢慢看。。。
初步做了下测试。


16楼 batman 耗时 0 小时 1 分钟 5 秒 31 毫秒

14楼 rat 耗时 0 小时 0 分钟 57 秒 40 毫秒 ...


13秒的处理 真高效
说实话 我想尽办法也没有让代码的效率的提高
我想我的以年递减 在确定日期方面一个也快的了
就是递加和判断方面  我想是少不了一条一条判断的
期待 随风兄的精彩代码

TOP

下面是我对自己16楼代码的测试结果:

但13秒多的速度,确实让人期待。。。
***共同提高***

TOP

  1. @echo off&setlocal enabledelayedexpansion
  2. cd.>c.txt
  3. echo %time%
  4. for %%a in (1 3 5 7 8 10 12) do set _%%a=31
  5. for %%a in (4 6 9 11) do set _%%a=30
  6. for /f "tokens=1-3 delims=- " %%a in ("%date%") do set/a "Year=%%a,Month=100%%b%%100,Day=100%%c%%100+1"
  7. for /f "delims=:" %%a in ('findstr /n /v $ "ab cd.txt"') do set /a "Line=%%a,Feb=28+^!(year%%4)"
  8. set "Monthes=1#31 2#%Feb% 3#31 4#30 5#31 6#30 7#31 8#31 9#30 10#31 11#30 12#31"
  9. for %%i in (%Monthes%) do for /f "tokens=1,2 delims=#" %%a in ("%%i") do if %%a leq %Month% set /a DayCount+=%%b
  10. for /f "tokens=%month%" %%a in ("%Monthes%") do for /f "tokens=1,2 delims=#" %%i in ("%%a") do set/a DayCount-=%%j-Day
  11. set /a LineTemp=Line-DayCount
  12. :loop
  13. set/a "LineTemp-=365+(^!(year%%4)&^!(^!(year%%100))|^!(year%%400)),Year-=1"
  14. if %LineTemp% geq 365 goto loop
  15. set/a "Year-=1,Month=12,Feb=28+^!(Year%%4)"
  16. :loop1
  17. if %LineTemp% gtr !_%Month%! (
  18.    for /f "tokens=%Month%" %%a in ("1#31 2#%Feb% 3#31 4#30 5#31 6#30 7#31 8#31 9#30 10#31 11#30 12#31") do (
  19.         for /f "tokens=1,2 delims=#" %%i in ("%%a") do set/a LineTemp-=%%j
  20.         set/a month-=1&goto loop1
  21. ))
  22. set /a Day=_%Month%-LineTemp
  23. for /f "usebackq delims=" %%a in ("ab cd.txt") do (
  24.       if !Month! lss 10 (set "Mon=0!Month!") else (set "Mon=!Month!")
  25.       if !Day! lss 10 (set "Da=0!Day!") else (set "Da=!Day!")
  26.       echo !Year!年!Mon!月!Da!日 %%a
  27.       set/a Day+=1
  28.       if !Day! GTR 28 CALL :MonitorMonthCount
  29. )>>c.txt
  30. echo %time%
  31. pause>nul&exit/b
  32. :MonitorMonthCount
  33. if %day% gtr !_%month%! set/a "day=1,month+=1"&echo.
  34. if !month! equ 13 set /a "month=1,year+=1,_2=28+(^!(year%%4)&^!(^!(year%%100)) | ^!(year%%400))"
复制代码
钻了一个空子,用findstr /n /v $ "ab cd.txt"来计算行数,当然最末行不能是空行。
心绪平和,眼藏静谧。

TOP

::递加日期,以处理5万行的文本为例
::本机测试   耗时: 0 小时 0 分钟 14 秒 72 毫秒
::这次测试怎么都要14秒。。郁闷!难道是电脑不同的原因?
代码效率关键是,for 内部运行的命令越少越好。
:
  1. @echo off&setlocal enabledelayedexpansion
  2. set ttime=%time%&set wjm=ab cd.txt
  3. for /f "tokens=2 delims=:" %%a in ('find /v /c "" "%wjm%"') do set /a tian=%%a-1
  4. call :Date2Day "%date:~0,10%" %tian% sy sm sd
  5. echo  %tian% 天前的日期是:%sy%年%sm%月%sd%日
  6. set /a sm+=100,sd+=100,n=100,yue113=131
  7. for %%a in (31 28 31 30 31 30 31 31 30 31 30 31) do set /a n+=1&set /a yue!n!=1%%a
  8. set /a yue102="^!(sy%%4)&^!(^!(sy%%100))|^!(sy%%400)+128",py=yue!sm!
  9. echo.1>nul 3>c.txt
  10. for /f "usebackq delims=" %%a in ("%wjm%") do (
  11.    echo !sy!年!sm:~-2!月!sd:~-2!日 %%a
  12.    set /a sd+=1
  13.    if !sd! gtr !py! (
  14.      set /a sd=101,sm+=1&set /a py=yue!sm!&echo.
  15.      if !sm! gtr 112 (
  16.         set /a sy+=1,sm=101,yue102="^!(sy%%4)&^!(^!(sy%%100))|^!(sy%%400)+128"
  17. )))
  18. echo.1>nul 4>con
  19. call :time0 "%ttime%" "%time%" ok
  20. echo  耗时: %ok%&title ok
  21. echo.&pause
  22. start notepad "c.txt"&exit  
  23. :Date2Day 获取指定天数的日期 (封装)
  24. setlocal&rem by Will Sort @cn-dos
  25. for /f "tokens=1-3 delims=/-, " %%a in ('echo/%~1') do (
  26. set /a yy=%%a,mm=100%%b%%100,dd=100%%c%%100)
  27. set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,j=153*m+2
  28. set /a j=j/5+dd+y*365+y/4-y/100+y/400-2472633
  29. set /a i=j-%~2,a=i+2472632,b=4*a+3,b/=146097,c=-b*146097,c/=4,c+=a
  30. set /a d=4*c+3,d/=1461,e=-1461*d,e/=4,e+=c,m=5*e+2,m/=153,dd=153*m+2,dd/=5
  31. set /a dd=-dd+e+1,mm=-m/10,mm*=12,mm+=m+3,yy=b*100+d-4800+m/10
  32. endlocal&set %3=%yy%&set %4=%mm%&set %5=%dd%&goto :EOF
  33. :time0  计算批处理运行时间(封装)
  34. setlocal&set /a n=0&rem by 随风 @bbs.bathome.net
  35. for /f "tokens=1-8 delims=.: " %%a in ("%~1:%~2") do (
  36. set /a n+=10%%a%%100*360000+10%%b%%100*6000+10%%c%%100*100+10%%d%%100
  37. set /a n-=10%%e%%100*360000+10%%f%%100*6000+10%%g%%100*100+10%%h%%100)
  38. set /a s=n/360000,n=n%%360000,f=n/6000,n=n%%6000,m=n/100,n=n%%100
  39. set "ok=%s% 小时 %f% 分钟 %m% 秒 %n% 毫秒"
  40. endlocal&set "%~3=%ok:-=%"&goto :eof
复制代码

[ 本帖最后由 随风 于 2008-10-20 17:04 编辑 ]
1

评分人数

    • terse: 精彩PB + 5 技术 + 1
技术问题请到论坛发帖求助!

TOP

简直无敌了,测试随风兄的代码:
心绪平和,眼藏静谧。

TOP

看代码真是累,若想完全看懂各位的代码太需要时间了。
略看了一下,发现大家都忽略了一个问题,就是代码中for循环时你们都用了 call  命令
5万行,即使只运行10分之一次,效率也是会被明显拖慢的。
在庞大的数据面前,即使是 set str=!str:~-2! 这样的语句都会对效率有一定影响。
另外:pusofalse 测试真的是7秒吗?
    我测试最好的都是 13 秒,难道真的和电脑有这么大的关系?
    各位测试的结果也贴出来看看好吗/?

[ 本帖最后由 随风 于 2008-10-20 17:58 编辑 ]
技术问题请到论坛发帖求助!

TOP

我512M内存,1.6G双核CPU,机器配置也不怎么样。
测试最长的耗时时间正好是8秒。
这次测试结果:
心绪平和,眼藏静谧。

TOP

TOP

2008-11-5号  23:18分左右测试的,
CPU :AMD 双核3800+
内存:2G DDR2

估计剩下的就和操作系统有关了。(我先前用计算π 的软件弄的机器很卡。)
应该和内存没什么关系了吧?
顺便新手来报道下,各位 午夜好。
[attach]1494[/attach]

TOP

返回列表