标题: [数值计算] [讨论]批处理按数字大小排序 [打印本页]
作者: youxi01 时间: 2007-11-8 18:33 标题: [讨论]批处理按数字大小排序
本帖最后由 pcl_test 于 2016-11-3 20:22 编辑
有以下几个数字(注:批处理中,数字超出2^31会自动当成字符串,如:set /a num=99999999999999就会出错)
包括特大数字,现需要对它们进行排序(由小到大)。如何处理?
数字有:- 123
- 65
- 9999999999999
- 11111111111111
- 44444456
- 879554213
- 658974452136541
复制代码
作者: namejm 时间: 2007-11-8 21:09
排序一般要用到sort,不过,sort是逐位做比较,比如sort认为12大于100,因为第二位上,2大于0。要避免这样的情况,可以考虑只对同一长度的数字串做比较。例如以下代码就可以成功解决逐位比较和超大数带来的问题,只不过效率比较低下:- @echo off
- setlocal enabledelayedexpansion
-
- :: 统计数字串的最大长度
- set max=0
- for /f %%i in (test.txt) do (
- set length=0
- call :CheckLength %%i
- if !length! geq !max! set max=!length!
- )
-
- :: 在文本最后插入空行,消除findstr整行匹配时忽略最后一行带来的影响
- echo.>>test.txt
-
- :: 对同一长度的数字串做比较
- for /l %%i in (1,1,%max%) do (
- set str=!str![0-9]
- for /f %%j in ('findstr /be "!str!" test.txt^|sort') do echo %%j
- )
- pause
- exit
-
- :CheckLength
- set str=%1
- :loop
- set /a length+=1
- set str=!str:~1!
- if defined str goto loop
- goto :eof
复制代码
作者: 随风 时间: 2007-11-8 22:20
对于findstr的表达式一直是晕晕的,对sort的用法也一直是晕晕的,
既然说sort可以对相同位数的数进行排序,且可以处理超大数,
那么用补零的办法似乎也可以,那样就可以不用findstr命令.
namejm 说的效率低,不知是因为用了findstr的原因么?
而且我用你的代码处理一个超大数时,222222222222222222222222222222222 findstr居然报错!!
不知道是我的findstr命令有问题,还是本就如此.
用补零的方法,感觉快些.
::- @echo off&setlocal enabledelayedexpansion
- if not "%1"==":" (
- for /f %%a in ('"%~0" :^|sort') do (
- for /f "tokens=1,2 delims=0" %%b in ("%%a") do (
- set num=%%b
- if "%%b"=="a" (echo 0) else echo !num:~0,-1!
- ))
- pause&exit
- )
- :: 统计数字串的最大长度
- set max=100
- for /f %%i in (a.txt) do (
- set length=100
- call :CheckLength %%i
- if !length! geq !max! set max=!length!
- )
- for /l %%a in (1 1 %max%) do set num=0!num!
- for /f %%i in (a.txt) do (
- set var=!num!%%i
- call echo %%var:~-!max!%%a
- )
- goto :eof
- :CheckLength
- set str=%1
- if "%str:~100,1%"=="" (goto :eof) else set str=!str:~100!
- :loop
- set /a length+=1
- set str=!str:~1!
- if defined str goto loop
- goto :eof
复制代码
[ 本帖最后由 随风 于 2007-11-9 20:11 编辑 ]
作者: youxi01 时间: 2007-11-8 22:23
2F的能满足要求,但是似乎效率确实不高...
个人 觉得 没必要 使用findstr,终究那个会影响效率。
可以采用的方法(思路):
获取位数,然后和该数字排在一起
举例,对于以下数字(10位以内):
9
85
765
6542
56987
可以这样处理:
1 9
2 85
3 765
4 6542
5 56987
然后再排,这样效率会提高很多...
当然,位数超过10的类同
作者: youxi01 时间: 2007-11-8 22:31
3F的代码不错,效率比较高啊
作者: youxi01 时间: 2007-11-8 22:36
3F补0的方法 比我的 4F提出来的 取位数 再“合成”的设想要好啊,赞一个,加分
作者: namejm 时间: 2007-11-8 23:03
4楼获取数字串长度值并和数字串并排的方法,实际上是很难实现的,因为sort并不能分离出同一长度的数字串;就算是分离出来了,还会生成临时文件;综合起来考虑的话,效率应该还没有2楼的高。
3楼补零的方法效率大为提升,并且不会导致产生findstr的错误,应该是这个问题的完美解决方案。顺便提醒一下,%~0 最好写成 "%~0" ,以避免特殊路径带来的影响。通过测试,用2楼的代码处理超过15位的数字就会产生错误,但是,单用findstr来搜索超过15位的数字时,并没有任何问题,可能是 findstr.exe 设计上的bug。
作者: xiaoxx 时间: 2008-4-28 18:42
没看懂程序的执行顺序
for /f %%a in ('"%~0" :^|sort')有什么作用
作者: 随风 时间: 2008-4-28 20:13
if not "%1"==":" (
for /f %%a in ('"%~0" :^|sort') do (
意识是,当%1不等于:冒号的时候,就运行这句,也就是第一次运行的时候,因为%1是空,也就是不等于:冒号, %~0代表自身 后面的:是给它的参数,就是再次运行自身,并给%1赋值为:冒号.当%1等于冒号时就运行下面的语句.运行完后,返回到%~0处,再把结果交给sort排序,最后输出..
作者: xiaoxx 时间: 2008-4-28 21:25
明白了 感谢
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |