标题: [分享]批处理分段法计算字符串长度 [打印本页]
作者: netbenton 时间: 2009-4-23 01:05 标题: [分享]批处理分段法计算字符串长度
受到拆半算法的启发,突然想到这种分段法。与大家分亨,不知道是否已有先例。
此方法无论是通用性和速度,都具有很大的优越性。-
- @echo off&setlocal enabledelayedexpansion
- set str=
- :rep
-
- :::::串长度计算代码:::::::::
- set/a end=8189,add=end
- :lp
- if %add%==1 goto :ok
- set /a ben=end-add,add=^(end-ben^)/30+1
- for /l %%a in (%ben%,%add%,%end%) do (if "!str:~%%a,1!"=="" set end=%%a&goto :lp)
- set end=0
- :ok
- :::::::::::::::::::::::::::::::
-
-
- ::测试用代码
- echo %end%
- set str=!str!a
- pause
- goto :rep
复制代码
作者: lxzzr 时间: 2009-4-23 01:08 标题: 何必这么复杂呢
- @echo off
- SETLOCAL ENABLEDELAYEDEXPANSION
- set /p a=请输入要计算长度的字符串:
- for /l %%a in (1,1,100000) do (
- set k=!a:~%%a,1!
- if not defined k (
- echo 字符串长度:%%a
- pause>nul
- exit
- )
- )
复制代码
[ 本帖最后由 lxzzr 于 2009-4-23 03:14 编辑 ]
作者: 随风 时间: 2009-4-23 02:04 标题: 回复 2楼 的帖子
lxzzr 版主想简单了吧。
你的代码1000000000000000000已经超出了cmd的最大数字范围,cmd把他当作字符串处理,所以很快,但%%a不可能得到最终的值,改为一百万再试试?
并且代码获取字符串长度后,如果还需要继续运行怎么办?- @echo off
- SETLOCAL ENABLEDELAYEDEXPANSION
- set /p a=请输入要计算长度的字符串:
- for /l %%a in (1,1,1000000) do (
- set k=!a:~%%a,1!
- if not defined k (
- echo 字符串长度:%%a
- goto loop
- ))
- :loop
- echo 这里还需要对字符串进行处理。
- pause
复制代码
作者: lxzzr 时间: 2009-4-23 03:15
随风版主说的是,我想的有点简单了....
作者: netbenton 时间: 2009-4-23 17:49
改了一下,减少了一次goto :lp循环,并且for /l 次数也从30降为21,速度有所提升- @echo off&setlocal enabledelayedexpansion
- set str=
- :rep
-
-
- set/a end=8189,add=end
- :lp
- if %add%==1 goto :ok
- set /a ben=end-add,add=^(end-ben+20^)/21
- for /l %%a in (%ben%,%add%,%end%) do (if "!str:~%%a,1!"=="" set end=%%a&goto :lp)
- set end=0
- :ok
- echo %end%
-
-
-
- set str=!str!a
- pause
- goto :rep
复制代码
二楼说的最简单的方法应该是这个吧:
str 为字符串变量-
- if not defined str set num=0&goto :ok
- for /l %%a in (0,1,8189) do (if "!str:~%%a,1!"=="" set num=%%a&goto :ok)
- :ok
复制代码
此法并非不可用,只是效率一般,串越长越慢
虽然只有一个for ,并且for /l的速度很快,但是也需要时间的
因为在系统在解释for /l时已经分配了8189次if "!str...命令行
[ 本帖最后由 netbenton 于 2009-4-23 17:56 编辑 ]
作者: 随风 时间: 2009-4-23 17:57 标题: 回复 5楼 的帖子
是否考虑写成 “函数”
作者: netbenton 时间: 2009-4-23 18:30
又改了一下,把8189改成了8190,否则最后一段取不到结果
写成函数如下:
- :::::::::::::::::::::::::::::::::::::::::
- :getstrlen 分段法取字符串长度
- :: 用法用途:
- :: 把代码放到批处理中作为函数使用
- :: 取指定字答串的长度
- :: 调用方法:
- :: call :getstrlen 字符串变量名 结果变量名
- ::::::::::::::::::::::::::::::::::::::::::
-
- setlocal enabledelayedexpansion
- set "str=!%1!"
- :rep
- set/a end=8190,add=end
- :lp
- if %add%==1 goto :ok
- set /a ben=end-add,add=^(end-ben+20^)/21
- for /l %%a in (%ben%,%add%,%end%) do (if "!str:~%%a,1!"=="" set end=%%a&goto :lp)
- set end=0
- :ok
- endlocal&set %2=%end%&goto :eof
复制代码
作者: netbenton 时间: 2009-4-24 00:53 标题: 没有goto :lp也可以了
-
- @echo off&setlocal enabledelayedexpansion
- set str=
- :rep
-
- ::变量ds用来指定分段数,可随意指定(2到8190)都可以。
- set/a ds=4,ds1=ds-1
-
- if not defined str set end=-1&goto :ok
- set/a end=0,add=8190
- for /l %%a in (0,1,14) do (
- if !add!==1 goto :ok
- set /a end+=add,ben=end-add,add=^(end-ben+ds1^)/ds
- for /l %%b in (!ben!,!add!,!end!) do (if not "!str:~%%b,1!"=="" set end=%%b)
- )
- :ok
- set /a end+=1
- echo !end! !str!
-
- set str=!str!a
- pause
- goto :rep
复制代码
可以做到随意n分段,分为2段时,就像随风版主的拆半法了,到底分多少段才是最快速的呢?
作者: raymai97 时间: 2011-12-12 21:00
回复 8# netbenton
请问可以解释一下何为“折半算法”吗?我看了半天头都晕了都不明白啊~
作者: garyng 时间: 2011-12-12 21:07
回复 9# raymai97
你的折半法是指 搜索 还是?
作者: raymai97 时间: 2011-12-12 21:15
回复 10# garyng
这个帖子的折半算法~ 效率高很多,问题是我不明白啊~
作者: garyng 时间: 2011-12-12 21:49
回复 11# raymai97
具体我也不清楚啦。。
可是效率极高!!
作者: CrLf 时间: 2011-12-12 22:08
回复 11# raymai97
回复 12# garyng
十进制8191=4096+2048+1024+512+256+128+64+32+16+8+4+2+1=二进制的1111111111111
用二进制来理解可能比较简单,先判断第一位(从左至右)的状态,大于则标记相应位为 1,小于则标记为 0。
作者: raymai97 时间: 2011-12-12 23:23
回复 13# CrLf
OMG你们这群数学天才,汇编对你们来说肯定是小意思了……
我真的很好奇你们的头脑是怎样练出来的,难道你们在学校数学都是拿第一的?
真的很佩服你们,你们几年前的帖子比我现在的水平还要高,恐怕外国人也没这么强……
ok切入正题,我还是不太明白这段:- set /a ben=end-add,add=^(end-ben^)/30+1
- for /l %%a in (%ben%,%add%,%end%) do (if "!str:~%%a,1!"=="" set end=%%a&goto :lp)
复制代码
先说上面那段:
ben=end-add(8189-8189)?
add=(end-ben)/30+1 (8189-0)/30+1
为何要除30+1呢?
作者: CrLf 时间: 2011-12-13 08:17
回复 14# raymai97
这跟数学好有什么关系...
那个代码中先除 30 再加 1 是用无限逼近的办法,类似于 batman 发过的开方算法
欢迎光临 批处理之家 (http://bathome.net./) |
Powered by Discuz! 7.2 |