[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[数值计算] [已解决]批处理怎么找出一组数字中的最小值?

本帖最后由 abcdshenji 于 2011-5-9 07:58 编辑

今天在网上瞎逛,偶然看到一个“找出一组数字中的最小值”的写法:
  1. @echo off
  2. set/p n=
  3. :p
  4. for /f "tokens=1* delims=." %%i in ("%n%") do set t=#######%%i&call set _%%t:~-8%%=a&if "%%j" neq "" set n=%%j&goto p
  5. for /f "delims==#_" %%i in ('set _') do echo %%i&pause&exit
复制代码
输入:100.50.200.300
输出:50

这段代码真是看的蛋疼。。。有哪位大师能详细解释一下它的思路是怎样的???
1

评分人数

    • Batcher: 感谢给帖子标题标注[已解决]字样PB + 2

有更好的算法:
  1. @echo off&setlocal enabledelayedexpansion
  2. set str=123,435,4,43,325,54,234,65,632,45,4342,4265,44,5464
  3. for %%a in (%str%) do (
  4. set /a "n+=^!((%%~a-n)>>31)*(%%~a-n)"
  5. )
  6. echo 最大值:!n!
  7. for %%a in (%str%) do (
  8. set /a "n-=^!((n-%%~a)>>31)*(n-%%~a)"
  9. )
  10. echo 最小值:!n!
  11. pause
复制代码
1

评分人数

    • abcdshenji: 琢磨了半小时终于明白了技术 + 1

TOP

思路是,在每个数字用#补足8位,将其定义成变量,利用set自动将其排序,最小的排第一。最后用for取第一个就是了

TOP

换一种更通俗的:
  1. @echo off&setlocal enabledelayedexpansion
  2. set str=123,435,4,43,325,54,234,65,632,45,4342,4265,44,5464
  3. set max=0
  4. for %%a in (%str%) do (
  5.    if %%~a gtr !max! set max=%%~a
  6. )
  7. echo 最大值:!max!
  8. set min=!max!
  9. for %%a in (%str%) do (
  10.    if %%~a lss !min! set min=%%~a
  11. )
  12. echo 最小值:!min!
  13. pause
复制代码

TOP

楼上能不能说说你那set/a的奥妙,看起来有点神奇!

TOP

2# zm900612


这个位运算看着不是一般的迷糊,憨豆先生能不能解释一下啊?

TOP

3# wankoilz


set还能排序哦?

TOP

4# zm900612


额。。学C的时候最简单的例子,用到这里了。。

TOP

7# abcdshenji


能。这是set命令的一个特性:
SET command invoked with just a variable name, no equal sign or value
will display the value of all variables whose prefix matches the name
given to the SET command.  For example:

    SET P

would display all variables that begin with the letter 'P'
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

5# wankoilz


和4楼代码是同一个思路,计算量接近,效率应该差不多,“^!((%%~a-n)>>31)”是判断%%~a(加~是为了严谨)是否小于n,小于则结果为0,否则为1,总之就是模拟判断两数大小的布尔运算,其他的应该很好理解了吧

TOP

本帖最后由 wankoilz 于 2011-5-8 11:16 编辑

有意思,最大数是加出来的,最小数是减出来的!
恕我话多,能不能把>>31,和!^的妙用一同说说,先谢过!

TOP

11# wankoilz

>>是位移,因为bat中正负数的存储方式有别,导致自然数位移超过其二进制形态的位数之后结果为0,而负数则为-1
!是布尔运算,若a为0,则!a为1,若a为1,则!a为0,也可以不要布尔运算,"n-=(1+(%%~a-n)>>31)*(%%~a-n)"意思是一样的,不过!的意图比较明了,易读性更强,至于^虽然本身也是运算符,但是由于此处开启了变量延迟,所以在计算之前还要经过一次预处理,!必须写为^!,而^必须写为^^,另外,若开启变量延迟的代码中要使用!,不光要用^转义,还要用上""

TOP

本帖最后由 wankoilz 于 2011-5-8 13:21 编辑

感谢楼上的详细讲解!原来可以用这种方法判断正负,你那set/a构造确实不错!那也可以这样来找最大数:set/a test=1/((%%a-max)>>31) 2>nul || set max=%%a
试了下set/a的另外两个一元运算符 _~ 好像也可以用来判断正负

TOP

本帖最后由 pcl_test 于 2017-3-19 05:53 编辑
  1. set/a test=1/((%%a-max)>>31) 2>nul || set max=%%a
复制代码
2楼和4楼的结合。。。。

TOP

9# Batcher


set 中下划线好像在起作用。。

得好好学习了。。

TOP

返回列表