中国DOS联盟论坛

中国DOS联盟

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

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

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
« [1] [2] »
作者:
标题: [求助]代码解释 上一主题 | 下一主题
ZJHJ
高级用户





积分 609
发帖 374
注册 2006-8-2
状态 离线
『楼 主』:  [求助]代码解释

我看到如下代码,非常精辟!求老师指点!
@echo off&setlocal enabledelayedexpansion
:: 代码5
:: Code by CN-DOS terse
set "hx=0123456789ABCDEF"
set/p str=:
for /l %%i in (1 1 8) do (
     if !str! GTR 0 (
        set/a "n=str&15,str>>=4"
        call set h=%%hx:~!n!,1%%!h!
     )
)
if not defined h set "h=0"
echo.%str% 的十六进制为:0x!h!
pause

1,
%%i 是从1取到8,为什么?却没有看到%%i 的去处?
2,
set/a "n=str&15,str>>=4"
是取余的意思,但怎么也看不懂.....

如果按我的写法却成了这样:

set /a y= str%%16
set /a ya=str/16%%16
set /a yb=str/256%%16
set /a yc=str/4096%%16
set /a yd=str/65536%%16
set /a ye=str/1048576%%16
set /a yf=str/16777216%%16
set /a yg=str/268435456%%16
set  m=0123456789ABCDEF
set  cdm=!m:~%yg%,1!!m:~%yf%,1!!m:~%ye%,1!!m:~%yd%,1!!m:~%yc%,1!!m:~%yb%,1!!m:~%ya%,1!!m:~%y%,1!

[ Last edited by ZJHJ on 2010-8-18 at 00:36 ]

2010-8-18 00:29
查看资料  发短消息 网志   编辑帖子  回复  引用回复
slore
铂金会员





积分 5212
发帖 2478
注册 2007-2-8
状态 离线
『第 2 楼』:  

那个循环只是控制循环次数为8次

主要是移位操作。。。具体含义可以google下相关位操作,  与运算,左移,右移



S smile 微笑,L love 爱,O optimism 乐观,R relax 放松,E enthusiasm 热情...Slore
2010-8-18 13:00
查看资料  发短消息 网志   编辑帖子  回复  引用回复
HAT
版主





积分 9023
发帖 5017
注册 2007-5-31
状态 离线
『第 3 楼』:  

批处理位运算以及原码、反码、补码的概念
http://bbs.bathome.net/thread-1844-1-1.html



2010-8-18 17:40
查看资料  发短消息 网志   编辑帖子  回复  引用回复
q8249014
初级用户





积分 175
发帖 45
注册 2007-8-4
状态 离线
『第 4 楼』:  

这段代码是我学习帖①中的一段实例演示代码,是我精简和修正过的

1。2147483647 的十六进制为:0x7FFFFFFF     set /a 的极限  [2^31-1]

     7FFFFFFF=8位       所以我们最多循环8次就可以啦

     for只是为了循环    %%i只是语法的需要  所以……

2。参考位运算的帖子

2010-8-20 11:10
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
doshsyy
新手上路





积分 19
发帖 15
注册 2010-8-20
状态 离线
『第 5 楼』:  

i只是控制循环次数为8次。
set/a "n=str&15,str>>=4"
n=str&15相当于C语言中的n=str%16,str&15中15二进制位1111,str的二进制与1111进行“&“即"与"运算,只取str二进制的最后四位,即str/
16的余数。例如:30&16-->00011110&1111=1110=14。即相当于30%16=14。
str>>4,str二进制右移四位,即丢失最后四位,相当于str=str/16然后取整,即C语言中的int str=str/16。
本来写的很详细的,但是说不让发。所以辛辛苦苦编辑的内容丢失了,只能简单点了。如果要怪,就怪论坛非得注册两个小时才可发言!(好像我注册了不止2个小时了,最后只能到命令行发帖,无语!)

[ Last edited by doshsyy on 2010-8-20 at 21:12 ]

2010-8-20 19:00
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
doshsyy
新手上路





积分 19
发帖 15
注册 2010-8-20
状态 离线
『第 6 楼』:  

我倒是觉得call set h=%%hx:~!n!,1%%!h!更难懂。为什么要加call,不加call为什么不对?

[ Last edited by doshsyy on 2010-8-23 at 13:41 ]

2010-8-20 19:03
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
ZJHJ
高级用户





积分 609
发帖 374
注册 2006-8-2
状态 离线
『第 7 楼』:  

这个  set/a "n=str&15,str>>=4" 还是难懂....
我觉得如果从原理学习的角度来理解,将代码写成这样就非常容易理解了:
@echo off
setlocal enabledelayedexpansion
set /p qw=输入十进制数字(极限值2147483647)
set m=0123456789ABCDEF
set /a y=qw,  ys=qw%%16
set    h=!m:~%ys%,1!
for /l %%i in (1 1 7) do (
    set /a y=!y!/16,  ys=!y!/16%%16
     call set h=%%m:~!ys!,1%%!h!
)
:ie
if %h:~0,1%==0 (
set h=%h:~1%
goto ie
)
echo %qw% 的十六进制为 !h!
pause

[ Last edited by ZJHJ on 2010-8-21 at 00:45 ]

   此帖被 +1 点积分    点击查看详情   
评分人:【 hsyy 分数: +1  时间:2010-8-21 11:24


2010-8-20 23:39
查看资料  发短消息 网志   编辑帖子  回复  引用回复
doshsyy
新手上路





积分 19
发帖 15
注册 2010-8-20
状态 离线
『第 8 楼』:  

恩,是难懂,但是代码简洁,并且调用的是系统的基本运算符,速度也快。这是批处理的运算符号的常用技巧。

2010-8-21 07:54
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
hsyy
新手上路





积分 6
发帖 2
注册 2010-8-21
状态 离线
『第 9 楼』:  我想测试下论坛的bug。

我想测试下论坛的bug。果然有,不过不是严重,不威胁安全。

[ Last edited by hsyy on 2010-8-21 at 08:07 ]

2010-8-21 08:05
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
ZJHJ
高级用户





积分 609
发帖 374
注册 2006-8-2
状态 离线
『第 10 楼』:  

如果把程序的效率看的很重要的话,我不认同代码简单效率就高。
我也做过试验:
连续处理1万组随机9位数,转化为十六进制。

如果用直显方式需要5分20秒

如果用 for /l %%i in (1 1 8) do (
     if !str! GTR 0 (
        set/a "n=str&15,str>>=4"
        call set h=%%hx:~!n!,1%%!h!
     )
)
用时约 13分15秒

如果用
:dycx
set /a y=qw,  ys=qw%%16
set    h=!m:~%ys%,1!
:bb
    set /a y=!y!/16,  ys=!y!/16%%16
    call set h=%%m:~!ys!,1%%!h!
if !y! GTR 0 goto bb

用时约 22分37秒

2010-8-23 12:39
查看资料  发短消息 网志   编辑帖子  回复  引用回复
slore
铂金会员





积分 5212
发帖 2478
注册 2007-2-8
状态 离线
『第 11 楼』:  

这个不是因为代码简单。。。位运算正好简单罢了……

理论上位运算速度快,所以代码用位操作。

是为了效率用位运算,不是因为位操作代码简洁。。。。


bat的解释执行不是我们能控制的,如果是高级语言绝对是位运算快。
这里还牵扯到字符串。。。

10楼的直接显示什么意思?直接echo没转换么?

看你的数据貌似用set/a "n=str&15,str>>=4"快8,9分钟?
但是和你说的
如果把程序的效率看的很重要的话,我不认同代码简单效率就高。
又不相符。。。。



S smile 微笑,L love 爱,O optimism 乐观,R relax 放松,E enthusiasm 热情...Slore
2010-8-23 12:59
查看资料  发短消息 网志   编辑帖子  回复  引用回复
doshsyy
新手上路





积分 19
发帖 15
注册 2010-8-20
状态 离线
『第 12 楼』:  

我没说代码简洁就会执行的效率高,我倒不会这么无知。要说代码质量,要考虑时间复杂度和储存空间需求,对小程序来说没有什么必要去考虑。对于大型程序来说是绝对有必要。对于上面的程序只是刚好可以用执行效率高的二进制位的逻辑运算与移位运算而且代码简洁。所以我才说“但是代码简洁,并且调用的是系统的基本运算符,速度也快。”,不知道你为什么说我说过代码简洁执行效率就高?还有,对于你得到的“直显方式”效率比直接的二进制执行效率高的结果我感到疑惑!

2010-8-23 13:53
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
doshsyy
新手上路





积分 19
发帖 15
注册 2010-8-20
状态 离线
『第 13 楼』:  

@echo off&setlocal enabledelayedexpansion
set t1=!time!
echo %t1%
for /L %%i in (1 1 10000) do (
        set /A str=!random!
        set s=!str!
        set hx=0123456789ABCDEF
        for /L %%j in (1 1 8) do (
                if !str! GTR 0 (
                        set /A "n=!str!&15,str>>=4"
                        call set h=%%hx:~!n!,1%%!h!
                )
        )
        if not defined h set "h=0"
        echo.!s! 的十六进制为:0x!h!
        set h=
)
set t2=!time!
echo %t2%
for /F "tokens=2,3delims=:" %%i in ("%t1%") do (
        set t1m=%%i
        set t1s=%%j
        set t1s=!t1s:~0,-3!
)
echo %t1m% !t1s!
for /F "tokens=2,3delims=:" %%i in ("%t2%") do (
        set t2m=%%i
        set t2s=%%j
        set t2s=!t2s:~0,-3!
)
echo %t2m% !t2s!
set /A "tm=%t2m%-%t1m%,ts=!t2s!-!t1s!"
echo %tm%:%ts%
pause
回显 1:2(1分02秒)
@echo off&setlocal enabledelayedexpansion
set t1=!time!
for /L %%i in (1 1 10000) do (
        set /A str=!random!
        set s=!str!
        set hx=0123456789ABCDEF
        for /L %%j in (1 1 8) do (
                if !str! GTR 0 (
                        set /A "n=!str!&15,str>>=4"
                        call set h=%%hx:~!n!,1%%!h!
                )
        )
        if not defined h set "h=0"
        echo !s!的十六进制为:0x!h!
        set h=
)
set t2=!time!
for /F "tokens=2,3delims=:" %%i in ("%t1%") do (
        set t1m=%%i
        set t1s=%%j
        set t1s=!t1s:~0,-3!
)
for /F "tokens=2,3delims=:" %%i in ("%t2%") do (
        set t2m=%%i
        set t2s=%%j
        set t2s=!t2s:~0,-3!
)
set /A "tm=%t2m%-%t1m%,ts=!t2s!-!t1s!"
echo %tm%:%ts%
pause
回显 1:1(1分01秒)
不知道10楼你怎么弄的,运行时间那么长,而且差距那么大,估计代码写错了吧!

2010-8-23 15:18
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
ZJHJ
高级用户





积分 609
发帖 374
注册 2006-8-2
状态 离线
『第 14 楼』:  

我的意思是说:
如果用for /l %%i in (1 1 8) do (
     if !str! GTR 0 (
        set/a "n=str&15,str>>=4"
        call set h=%%hx:~!n!,1%%!h!
     )
)
或者用 for /l %%i in (1 1 7) do (
    set /a y=!y!/16,  ys=!y!/16%%16
    call set h=%%m:~!ys!,1%%!h!
)
的方式,即for循环代码都很简单,但是处理速度并不快。用时约 13分15秒
如果用
:bb
    set /a y=!y!/16,  ys=!y!/16%%16
    call set h=%%m:~!ys!,1%%!h!
if !y! GTR 0 goto bb
方式处理,代码也很简单,但是处理速度却最慢。用时约 22分37秒
如果用

set /a y= qw%%16
set /a y1=qw/16%%16
set /a y2=qw/256%%16
set /a y3=qw/4096%%16
set /a y4=qw/65536%%16
set /a y5=qw/1048576%%16
set /a y6=qw/16777216%%16
set /a y7=qw/268435456%%16
set h=!m:~%y7%,1!!m:~%y6%,1!!m:~%y5%,1!!m:~%y4%,1!!m:~%y3%,1!!m:~%y2%,1!!m:~%y1%,1!!m:~%y%,1!
的方式是最快的,需要5分20秒

问题出在for或goto

[ Last edited by ZJHJ on 2010-8-23 at 19:08 ]

附件 1: 代码比较.rar (2010-8-23 19:04, 44.8 K, 下载附件所需积分 1 点 ,下载次数: 4)
2010-8-23 19:04
查看资料  发短消息 网志   编辑帖子  回复  引用回复
HAT
版主





积分 9023
发帖 5017
注册 2007-5-31
状态 离线
『第 15 楼』:  Re 6 楼

变量延迟扩展和变量嵌套的基础知识



2010-8-24 11:18
查看资料  发短消息 网志   编辑帖子  回复  引用回复
« [1] [2] »
请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: