中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

中国DOS联盟论坛
现在时间是 2026-06-14 20:58
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » 关于去最大值去最小值,中间值求平均数的脚本
楼 主 关于去最大值去最小值,中间值求平均数的脚本 发表于 2006-05-24 13:26 ·  中国 山西 运城 电信
中级用户
★★
积分 241
发帖 131
注册 2005-09-28 19:01
UID 42920
性别 男
状态 离线
如题:
比如有一组数值,是否可以用批处理或者VBS脚本,去除其中的最大最小值,然后其余的数值求平均值?
房东说:这娃是个好孩子!
2 发表于 2006-05-25 21:28 ·  中国 湖北 荆门 电信
荣誉版主
★★★
积分 2,013
发帖 718
注册 2006-02-18 07:07
UID 50550
状态 离线
当然可以,如果用JS的话,它带有一个排序函数:sort,用来解决是很简单的,如果用VBS,也有多种方法,最理想的莫过于利用创建断开的数据集对象来操作,可以像操作数据库一样来编辑那些数据,还能保存为各种格式的文件,不过,在中国DOS联盟,我还是给你个命令行下的批处理版吧:

@echo off
set Count=10 rem 参加计算的数的个数
call :GetNum %Count% rem 产生随机数
echo 要处理的数据为:%Num%
call :EditNum %Num%
pause
exit

:EditNum
set /a intMax=1,intMin=2147483647 rem 批处理最大只能处理32位数据
setlocal enabledelayedexpansion
for %%i in (%*) do (if %%i GEQ !intMax! set /a intMax=%%i) & (if %%i LEQ !intMin! set /a intMin=%%i)
for %%j in (%*) do set /a intCount=!intCount! + 1
echo 有%intCount%个数,其中最大和最小分别为%intMax%,%intMin%
set total=%Num: =+%
set /a total=%total%
set /a total=(%total% - %intMax% - %intMin%) / (%intCount% - 2)
echo 总数为:%total%
goto end

:GetNum
if "%Flag%" == "%1" goto end
set Num=%Num% %Random%
set /a Flag = %Flag% + 1
goto GetNum

:end
endlocal
set Flag=
set intMax=
set intMin=
set intCount=
set total=
3 发表于 2006-05-25 22:57 ·  中国 山西 临汾 中移铁通
元老会员
★★★★
Batchinger
积分 4,432
发帖 1,512
注册 2002-10-18 00:00
UID 19
性别 男
状态 离线
Re 3742668:

很不错的方案。

只是似乎intMax的初值似应取-2147483648,或者intMax和intMin都取%1初值也是可以的。

另外,:EditNum使用了全局变量%Num%,虽然这是一个很巧妙的技巧,但它不符合局部模块不应访问全局变量的习惯,通用性被降低了,通常我们是在判断最小值和最大值的循环中求得变量和的,同时可以进行一些溢出错误处理。
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
4 发表于 2006-05-25 23:14 ·  中国 湖北 荆门 电信
荣誉版主
★★★
积分 2,013
发帖 718
注册 2006-02-18 07:07
UID 50550
状态 离线
对于intMax的初值开始是考虑过,不过考虑到%random%只能产生1-32767之间的数,所以就选择的是1,至于intMin用2147483647是因为觉得32767的范围似乎太小了一点,再说正整数的比较是比较常见的。
至于访问%Num%全局变量的问题,如果是用VBS或者其他的话,可能不会出现这种情况,只不过实在懒得去多写一个for来从%*获得算式,因为我认为在批处理中并不存在什么局部变量,统统都是全局变量。
5 发表于 2006-05-25 23:24 ·  中国 山西 临汾 中移铁通
元老会员
★★★★
Batchinger
积分 4,432
发帖 1,512
注册 2002-10-18 00:00
UID 19
性别 男
状态 离线
Re 3742668:

你的代码不应该只能适应你的测试数据,我们无法假定测试数据必然是正整数,所以初值的修改还是必要的。

2147483647是个与环境相关的数,我们在设计算法时应避免使用,否则如果在64位的系统中可能会出现问题。

批处理中是存在局部变量的,至少在CMD中,我们可以使用setlocal来限定变量的作用域和生存周期。

如果将你的:EditNum移植到其他程序中或者直接调用它,则很可能出现问题。

求和和求个数可以在判断最小值和最大值的for循环一体实现,并不很麻烦。

[ Last edited by willsort on 2006-5-25 at 23:27 ]
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
6 发表于 2006-06-02 22:54 ·  中国 山西 太原 电信
中级用户
★★
积分 241
发帖 131
注册 2005-09-28 19:01
UID 42920
性别 男
状态 离线
我的意思是,能不能打开后,程序等待输入数字,这些数字可能是N个,然后去大去小,最后的求平均值!
房东说:这娃是个好孩子!
7 发表于 2006-06-03 19:33 ·  中国 山西 临汾 中移铁通
元老会员
★★★★
Batchinger
积分 4,432
发帖 1,512
注册 2002-10-18 00:00
UID 19
性别 男
状态 离线
Re maya0su:

有了 3742668 兄的代码在前,编写等待输入求平均数的代码应该不是很难,根据你的要求作了相应的修改。


:: Average.cmd - Eval average of a batch of numbers
:: Will Sort - 2006-06-03 - CMD@WinXP
@echo off
call :GetNum
echo 要处理的数据为:%return%
call :Average %return%
echo 去除最大值和最小值的平均数为 %return%
goto :eof

:GetNum
if "%_n%"=="" setlocal
set _n=-
set /p _n=请输入一个整数(直接回车结束输入):
if "%_n%"=="-" endlocal&set return=%return%&goto :eof
set /a _i=_n
if "%_i%" NEQ "%_n%" (echo 无效的输入数据:%_n%
) else set return=%return% %_i%
goto GetNum

:Average
setlocal EnableDelayedExpansion
if "%3"=="" set return=N/A&goto :eof
set /a iMax=%1,iMin=%1
for %%i in (%*) do (
if %%i GTR !iMax! set /a iMax=%%i
if %%i LSS !iMin! set /a iMin=%%i
set /a iTotal+=%%i
set /a iCount+=1
)
set /a return=(iTotal-iMax-iMin) / (iCount-2)
endlocal&set return=%return%&goto :eof
※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得!
8 发表于 2006-07-24 14:09 ·  中国 山西 运城 电信
中级用户
★★
积分 241
发帖 131
注册 2005-09-28 19:01
UID 42920
性别 男
状态 离线
又有一个新的问题出现了
我想利用另一个批处理调用此程序,从而实现循环
@echo off
:loop
cls
call itbat.bat


set /p start=是否继续?(是Y 否N)
if "%start%"=="y" goto :loop
if "%start%"=="n" goto :end

:end
exit

在实现循环的过程出现了一个现象就是
上次计算后的结果,也就是那个平均值会出现下一次的输入数中
同时也参与下一次的运算!
请问有办法解决吗?

[ Last edited by maya0su on 2006-7-24 at 14:11 ]
房东说:这娃是个好孩子!
9 发表于 2006-07-24 17:25 ·  中国 四川 成都 鹏博士宽带
荣誉版主
★★★★
batch fan
积分 5,226
发帖 1,737
注册 2006-03-10 00:38
UID 51697
来自 成都
状态 离线
  问题出在call :Average %return%这一句。如果在循环调用的时候能清空%return%的值就好办了。
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
10 发表于 2006-07-24 18:30 ·  中国 广西 玉林 博白县 电信
金牌会员
★★★★
积分 3,687
发帖 1,467
注册 2005-08-08 12:00
UID 44210
状态 离线
直接在“call itbat.bat”后加入“set return=”不就行了么
11 发表于 2006-07-24 22:09 ·  中国 四川 成都 鹏博士宽带
荣誉版主
★★★★
batch fan
积分 5,226
发帖 1,737
注册 2006-03-10 00:38
UID 51697
来自 成都
状态 离线
  呵呵,楼上的,我也曾有过这样的冲动,可是,你试验过了吗?发言要慎重哦。
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
12 发表于 2006-07-25 00:39 ·  中国 广西 玉林 博白县 电信
金牌会员
★★★★
积分 3,687
发帖 1,467
注册 2005-08-08 12:00
UID 44210
状态 离线
Originally posted by namejm at 2006-7-24 22:09:
  呵呵,楼上的,我也曾有过这样的冲动,可是,你试验过了吗?发言要慎重哦。

改一下willsort版主的:
:: Average.cmd - Eval average of a batch of numbers
:: Will Sort - 2006-06-03 - CMD@WinXP
@echo off
set return=
call :GetNum
echo 要处理的数据为:%return%
call :Average %return%
echo 去除最大值和最小值的平均数为 %return%
goto :eof

:GetNum
if "%_n%"=="" setlocal
set _n=-
set /p _n=请输入一个整数(直接回车结束输入):
if "%_n%"=="-" endlocal&set return=%return%&goto :eof
set /a _i=_n
if "%_i%" NEQ "%_n%" (echo 无效的输入数据:%_n%
) else set return=%return% %_i%
goto GetNum

:Average
setlocal EnableDelayedExpansion
if "%3"=="" set return=N/A&goto :eof
set /a iMax=%1,iMin=%1
for %%i in (%*) do (
if %%i GTR !iMax! set /a iMax=%%i
if %%i LSS !iMin! set /a iMin=%%i
set /a iTotal+=%%i
set /a iCount+=1
)
set /a return=(iTotal-iMax-iMin) / (iCount-2)
endlocal&set return=%return%&goto :eof
set return=

OK

或者maya0su的:
@echo off
:loop
cls
set return=
call itbat.bat
set return=


set /p start=是否继续?(是Y 否N)
if "%start%"=="y" goto :loop
if "%start%"=="n" goto :end

:end
exit

也OK

[ Last edited by zxcv on 2006-7-25 at 00:41 ]
13 发表于 2006-07-25 12:50 ·  中国 四川 成都 鹏博士宽带
荣誉版主
★★★★
batch fan
积分 5,226
发帖 1,737
注册 2006-03-10 00:38
UID 51697
来自 成都
状态 离线
  原来是要加两处,zxcv的代码不错。看来自己得对 call 标号 参数 的格式多加揣摩才是。
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
论坛跳转: