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

【练习-046】批处理逆转整数二进制位的顺序

目的:练习批处理的位操作
要求:1、输入一个整数value,编程实现把value的二进制位模式从左到右变换。
           2、程序不依赖于你的机器上整数的字长,具有可移植性。
举例:输入25,在32位机器上,二进制位:00000000000000000000000000011001,编程使之变成-1744830464,
          二进制为:10011000000000000000000000000000。
加分:完成要求一,加五分;两个都完成,加十分。

[ 本帖最后由 lhjoanna 于 2009-4-26 18:17 编辑 ]

原帖由 lhjoanna 于 2009-5-1 11:54 发表
兄的代码在负数情况有些小问题

是的  有问题  这样呢
  1. @echo off&setlocal enabledelayedexpansion
  2. set/p a=INPUT:
  3. for /l %%i in (31,-1,0) do (
  4.     set/a "n=a&1,a>>=1,d+=n<<%%i"
  5.     set b=!b!!n!
  6.   )
  7. echo Decimal:%d% &echo Binary :%b%
  8. pause
复制代码
1

评分人数

TOP

兄的代码在负数情况有些小问题

TOP

以前写的2进制转换的  改下 不知通否
  1. @echo off&setlocal enabledelayedexpansion
  2. set/p a=INPUT:
  3. set i=1
  4. for /l %%i in (31,-1,0) do (
  5.     set/a n=^!^(^!^(a%%2^)^)2>nul
  6.     set/a i*=n"<<"%%i,d+=i,i=1
  7.     set b=!b!!n!
  8.     if !a! geq 2 (set/a a/=2)else set a=0
  9.   )
  10. echo Decimal:%d% &echo Binary :%b%
  11. pause
复制代码

TOP

今天忽然想到了用递归来算,代码以32位为例,效率也没有纯位运算高,仅作研究。
  1. @echo off
  2. set /p "value=INPUT:"
  3. set /a "i=1<<31",flag=1
  4. call :loop %i%
  5. pause>nul&goto :eof
  6. :loop
  7. set /a "i=%1,n=i&value,i>>=1,n=!(!n)"
  8. if %flag% equ 1 set /a i="1<<30" &set flag=0
  9. if %i% neq 0 (call :loop %i% %n%) else <nul set /p=%n%
  10. <nul set /p=%2
复制代码

TOP

Re:netbenton
         执行结果,要求都正确,代码还有几处可以精简的地方。进入循环刚开始的四个变量清空操作可以在循环首尾用一对setlocal enabledelayedexpansion和endlocal代替。还有可移植性的另一种思路在12楼与15楼都有体现!

TOP

re 楼主

已经解决通用和符号问题
  1. @echo off&setlocal enabledelayedexpansion
  2. set/a len=1,n=1
  3. :rep
  4. set/a len=len+len,n=n^<^<len,1/n 2>nul&&goto :rep
  5. :lp
  6. (set n=
  7. set o=
  8. set s=
  9. set ns=
  10. echo.
  11. set /p n=输入一个整数:)
  12. (if "%n%"=="" goto :eof
  13. for /l %%a in (1,1,!len!) do (
  14. set/a m=n%%2,n=n^>^>1,m*=m
  15. set s=!s!!m!
  16. set o=!m!!o!
  17. set/a ns=^(ns^<^<1^)+m
  18. )
  19. echo 正二进制:!o!   {%n%}
  20. echo 逆转输出:!s!   {!ns!}
  21. goto :lp)
复制代码
真的还可以精简,把一些地方换成了按位运算,更快更简
但初始化还是保持用set,反正只有四行,按字数来算还更少一点。
  1. @echo off&setlocal enabledelayedexpansion
  2. set/a len=1,n=1
  3. :rep
  4. set/a "len<<=1,n<<=len,1/n" 2>nul&&goto :rep
  5. :lp
  6. set n=&set o=&set s=&set ns=&echo.&set /p n=输入一个整数:
  7. (if "%n%"=="" goto :eof
  8. for /l %%a in (1,1,%len%) do (
  9. set/a "m=n&1,n>>=1,ns=ns<<1|m"
  10. set s=!s!!m!
  11. set o=!m!!o!
  12. )
  13. echo 正二进制:!o!   {%n%}
  14. echo 逆转输出:!s!   {!ns!}
  15. goto :lp)
复制代码

[ 本帖最后由 netbenton 于 2009-4-27 22:44 编辑 ]
1

评分人数

    • lhjoanna: 不错,代码还可再精简!PB + 8

TOP

Re:netbenton
        我想正确的思路是不能留下隐患,至于有没有512的我不清楚,但计算机是不断发展的,也要考虑程序能适应以后的发展。当然在效率要求不是太严格或如需改变但代码变动不大的情况下也可以。
    还有个小问题,就是兄的代码在输入负数的情况下,逆转后的十进制数的正负存在点儿小问题。

TOP

@echo off&setlocal enabledelayedexpansion
set len=1&for /l %%a in (1,1,256) do (set/a len=len^<^<1,1/len 2>nul || (set len=%%a&goto :lp))
set len=512&rem 首先测出字长,应该达不到512位吧?
:lp
(set n=
set o=
set s=
set ns=
echo.
set /p n=输入一个整数:)
(if "%n%"=="" goto :eof
for /l %%a in (1,1,!len!) do (
        set/a m=n%%2,n=n^>^>1
        set s=!s!!m:~-1!
        set o=!m:~-1!!o!
        set/a ns=^(ns^<^<1^)+m
)
echo 正二进制:!o!   {%n%}
echo 逆转输出:!s!   {!ns!}
goto :lp)

TOP

对于具体的某台机器,当然会与字长有关。机器的字长不同,那么逆转后的结果就不同。这也就是采用goto而不是for的原因,这也是兼顾效率与可移植性的方案。
    不知兄所说的不用二进制位几步就可以得出的是什么方法,有什么思路?我觉得位运算已经是几步就可以逆转,当然是要进行循环的。
  1. @echo off
  2. set /p "value=INPUT:"
  3. set /a i=1,answer=0
  4. :begin
  5. set /a "answer<<=1,b=value&1"
  6. set /a "answer|=b,value>>=1,i<<=1"&set "binary=%binary%%b%"
  7. if %i% neq 0 goto begin
  8. echo Decimal:%answer% &echo Binary :%binary%
  9. pause>nul
复制代码

TOP

感觉这样还是与字长有关啊(虽然没有直接使用字长,但还是要判断的)。我是想,如果不考虑写出数字的二进制形式,能不能通过较为简单的方法(不要goto循环),几步就能得出逆转结果。

又觉得,位运算应该必然与字长有关吧。

[ 本帖最后由 zqz0012005 于 2009-4-27 12:15 编辑 ]
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

Re:zqz
     呵,兄已经完成了两个要求,此句 if %check% neq 0 goto lp  保证只要%check%不为0就继续循环,这就使循环的次数与机器的字长无关!

[ 本帖最后由 lhjoanna 于 2009-4-27 12:01 编辑 ]

TOP

  1. @echo off
  2. set num=25
  3. set /p "num=Input:\>"
  4. :lp
  5. set /a "bit = num >> n & 1"
  6. set binary=%bit%%binary%
  7. set reverse=%reverse%%bit%
  8. set /a "num2 = num2 << 1 | bit"
  9. set /a "n += 1", "check = 1<<n"
  10. if %check% neq 0 goto lp
  11. echo num : %num%
  12. echo binary : %binary%
  13. echo reverse : %reverse%
  14. echo decimal : %num2%
  15. pause
复制代码
不知道怎样才能不涉及对字长的判断。
1

评分人数

    • lhjoanna: 兄已经完成了两个要求!PB + 10
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

Re:Pusofalse
         兄的代码还可再精简,在正数时输出最好补全后面的0,负数时忘记逆转了吧?

TOP

发个以前写的,感觉复杂了好多,只是转2进制
  1. @Echo Off
  2. Set /p num=Input:
  3. Call :ToBinary %num% sBinaryString
  4. Echo %sBinaryString%
  5. Pause & Exit /b
  6. :ToBinary numeric, ByRef sBinaryString
  7. SetLocal ENABLEEXTENSIONS
  8. Set "sResult="
  9. Set /a iTopBit = 0, iUnsignedNumber = %~1 "&" 0x7FFFFFFF
  10. If %~1 lss 0 (set /a iTopBit = 1)
  11. If %~1 gtr 0x7fffffff (set /a iTopBit = 1)
  12. :LoopToBinary ###INTERNAL-USED-ONLY###
  13. Set /a iTempNum = iUnsignedNumber "&" 1, iUnsignedNumber ">>=" 1
  14. Set "sResult=%iTempNum%%sResult%"
  15. If %iUnsignedNumber% gtr 0 (goto :LoopToBinary)
  16. EndLocal & Set "%2=%iTopBit%%sResult%" & Exit /b 0
复制代码

[ 本帖最后由 pusofalse 于 2009-4-27 09:49 编辑 ]
心绪平和,眼藏静谧。

TOP

返回列表