返回列表 发帖
终于将效率问题解决了,但代码确实难读了。。。
说明一下:先计算出文本的总行数,然后用渐近法计算出第一个日期(先算年再算月和日)
,然后再用for在按行读取数据时进行日期的累加和输出到新文本。
@echo off&setlocal enabledelayedexpansion
set "t=%time%"&echo.>c.txt
rem 提出当前的年月日数值
set /a year=%date:~,4%,month=1%date:~5,2%%%100,day=1%date:~8,2%%%100
rem 设置变量
for %%i in (31 29 31 30 31 30 31 31 30 31 30 31) do (
    set /a num+=1&set "_!num!=%%i"
    set "code1=!code1! %%i"&set "code2=!code2! !num!#%%i"
)
rem 获取文本总行数
for /f "usebackq delims=" %%i in ("ab cd.txt") do set /a n+=1
rem 计算并减去本年已过的天数
set /a n=n-day
for %%a in (%code1%) do (
    if "!m!" neq "%month%" (
       set /a n-=%%a,m+=1
       ) else (
       goto lp1
   )
)
:lp1
rem 计算初始年份
set /a year-=1,n-=365
set /a a=year%%4,b=year%%100,c=year%%400,yun=28,_2=28
if %b% equ 0 (
   if %c% equ 0 set /a n-=1,yun+=1,_2+=1
   ) else (
   if %a% equ 0 set /a n-=1,yun+=1,_2+=1
)
if %n% geq 0 goto lp1
set "code1=!code1:29=%yun%!"&set "code2=!code2:29=%yun%!"
rem 计算初始月份和日期
for %%a in (%code2%) do (
    for /f "tokens=1,2 delims=#" %%i in ("%%a") do (
        set /a n+=%%j
        if !n! geq 0 set /a month=%%i-1,day=%%j-n&goto next
    )
)
:next
rem 核心代码部分,读取文本内容并递加日期,输出到新文本
for /f "usebackq delims=" %%i in ("ab cd.txt") do (
    set /a n=day-_!month!
    if !n! gtr 0 call :lp2
    if !month! geq 10 (
       if !day! geq 10 (
          echo !year!!month!!day!%%i>>c.txt
          ) else (
          echo !year!!month!0!day!%%i>>c.txt
       )
       ) else (
       if !day! geq 10 (
          echo !year!0!month!!day!%%i>>c.txt
          ) else (
          echo !year!0!month!0!day!%%i>>c.txt
       )
    )
    set /a day+=1
)
echo 开始时间:%t%
echo 结束时间:%time%
pause>nul&goto :eof
:lp2
rem 子程序:跨月、跨年的计算和判断
echo.>>c.txt
set /a month+=1,day=1
if %month% equ 13 (
   set /a year+=1,month=1,a=year%%4,b=year%%100,c=year%%400,_2=28
   if !b! equ 0 (
      if !c! equ 0 set "_2=29"
      ) else (
      if !a! equ 0 set "_2=29"
   )
)COPY

[ 本帖最后由 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

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

TOP

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

[ 本帖最后由 随风 于 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

返回列表