Board logo

标题: [挑战4]: 乱序数值的提取与计算 [难度:★☆] [打印本页]

作者: flyinspace     时间: 2007-5-1 06:02    标题: [挑战4]: 乱序数值的提取与计算 [难度:★☆]

---------------------------------------------------------------------------------------------------- set "num1=flyi2007tianya04a30weltia16350pla1234567890y" set "num2=cn2102-dos4567aza1156.azx17173163lix;aeac1234567890v" 要求:提取所有的数字。例如: num1中,我们要提取出 : 2007 04 30 16350 1234567890这五个数值。 并计算 2007*4*30*16350*1234567890 的结果。 ---------------------------------------------------------- 同样的,在num2中,我们也要计算提取出来的数字的乘积。 然后比较 num1 和 num2 的大小。 获得 num1-num2 的精确结果。并输出。(科学计数法无效) 难点: 乱序数值的提取(无规律),乘法和减法的溢出位计算。大数的比较。 目标人群:针对会活用CMD基础的人 编写积分奖励:4分,完成难点中任意一点的人都可以获得一分的奖励 限制:不得使用第三方工具 使用:cmd(help中包含的指令).vbs 自带的函数库(不得使用 windows 的api。) ps : 积分不是目的。。重要的是,我们可以完成这样的挑战。。 请大家根据自己的能力尽力编写吧:) --------------------------------------------------------------------------------------------------------- 挑战系列5后,将会在每周一的时间里出一期新的挑战系列。 望各位高手鼎立支持。 个人代码随后奉上。 [ Last edited by flyinspace on 2007-4-30 at 05:48 PM ]

作者: zhoushijay     时间: 2007-5-1 06:25
最后的 1234567890 不需要乘吗? num1和num2是不是指乘过后的积

作者: flyinspace     时间: 2007-5-1 06:28
不好意思,我的疏忽。。 最后的1234567890也需要代入乘积的。。 num1 和 num 2 的值为提取出来的数值的乘积。 当然你也可以用 其他的变量来表示。 [ Last edited by flyinspace on 2007-4-30 at 05:30 PM ]

作者: lxmxn     时间: 2007-5-1 06:30
Re flyinspace: 感谢兄发的几个“挑战”系列的贴子,这样是非常有意义的,不仅有利于大家的技术交流,更有利于论坛的发展和人气的提升,特加分鼓励一下。

作者: flyinspace     时间: 2007-5-1 06:33
Originally posted by lxmxn at 2007-4-30 05:30 PM: Re flyinspace: 感谢兄发的几个“挑战”系列的贴子,这样是非常有意义的,不仅有利于大家的技术交流,更有利于论坛的发展和人气的提升,特加分鼓励一下。
呵呵,谢谢斑竹的加分,但我们更期待的是:斑竹精彩的代码回复。

作者: flyinspace     时间: 2007-5-2 14:02
这一题: 我也没有想到好法子。。本想利用人工演算乘法的方法解决(无奈代码太多,其中甚至包含了(加法,移位,减法)) 如此一来,代码实在比较长了。个人对这一题的难度把握错误(而且计算乘法运算的时候,尚有部分数据会有点差错,研究原因中……) 认为此题的难度应该为:☆☆☆ 不知各位达人有什么更好的方法没?

作者: slore     时间: 2007-5-2 15:42
提取比较都简单就是要精确非E或D的表达这个不好实现。。。。

作者: flyinspace     时间: 2007-5-2 17:11
嗯。提取的确好简单的。。。 主要是乘法运算不出错的表达很困难。。 两个数相乘。若两个数字的长度小于等于9 则调用自带的来完成。。 但若两个数都大于9。。 感觉人工算法不太好。。 有点想考虑 使用 2进制的方法来表达了。。但用批处理会算死人的。 而且批处理,又有一点搞不好了。 例如: set xx=123123。 不知道如何用最简单的方法修改第二个数字2 为我所需要的数字。。 只会调用函数相互更改。 批处理数组的功能太弱。。 真有点想用c++来解决问题。

作者: slore     时间: 2007-5-2 17:19
set xx=123123 set yy=%xx:~0,1%S%xx:~2,-1% echo %yy% pause 晕,最后位不好取,要么获取长度那也麻烦=。=

作者: flyinspace     时间: 2007-5-2 17:21
长度可以不用担心。 因为若不指定长度的话。会给出默认值的。 不过我的方法是调用函数获取长度。

作者: youxi01     时间: 2007-5-2 17:39
5.1假期没人陪,也上不了网,很郁闷。倒也多出了时间来思考人生的问题(庸庸碌碌、浑浑噩噩),也有了时间来讨论 联盟上的问题,呵呵。 写了一段 很混乱 的代码,欢迎测试指正。
::code by youxi01@cn-dos.net
@ECHO OFF
setlocal enabledelayedexpansion
title 乱序数值的提取与计算
color 1f
set "str1=flyi2121212t2fds654654546654654654654656521d5g615"
set "str2=wo6654541s1545446ffd6551323"
set/a m=0
echo 正在提取str1中的数值...
echo.
echo 提取出的数值有:
echo.
call :GetStr "%str1%"
set Rnum
echo ---------------------------------------
set/a Resstr=1
echo 正在求取str1中各数值之积...
echo.
FOR /F "delims== tokens=2" %%i in ('set Rnum') do call :Multi !Resstr! %%i
set num1=!Resstr!
echo 计算结果为:%num1%
for /l %%i in (1 1 %i%) do set Rnum%%i=
set/a i=0,Resstr=1
echo ---------------------------------------
echo 正在提取str2中的数值...
echo.
echo 提取出的数值有:
echo.
call :GetStr "%str2%"
set Rnum
echo ---------------------------------------
echo 正在求取str2中各数值之积...
FOR /F "delims== tokens=2" %%i in ('set Rnum') do call :Multi !Resstr! %%i
set num2=%Resstr%
echo 计算结果为:%num2%

echo ---------------------------------------
echo 正在比较大小...
echo.
if %num1% lss %num2% (
      echo num1 比 num2 小
      call :Sub %num2% %num1%) else (
          echo num1 比 num2 大
          call :Sub %num1% %num2%)

for /f "delims=0 tokens=*" %%i in ("!OKstr!") do echo 它们的差值为:%%i

pause>nul

:GetStr OBJ
   set "str=%~1"
   set/a i=1
   for /l %%i in (0 1 10000) do (
       set "Tstr=!str:~%%i,1!"
       IF "!Tstr!"=="" call :Check Rnum!i! & goto :eof
       IF !Tstr! GEQ 0 IF !Tstr! LEQ 9 (call set Rnum!i!=%%Rnum!i!%%!Tstr!) else (
            if defined Rnum!i! call :Check Rnum!i! & set/a i+=1))
       goto :EOF
         
:Check OBJ
   for /f "delims=0 tokens=*" %%i in ("!%1!") do set %1=%%i
   GOTO :EOF

:Split OBJ num(i)Name CX
   set Rstr=%~1
   if %Rstr% LEQ 10000 set "%2!%3!=%Rstr%" & goto :eof
   set/a %2!%3!=10000%Rstr:~-4%%%10000
   set/a %3+=1
   call :Split %Rstr:~0,-4% %2 %3
   goto :eof

:Multi
set/a m=0,n=0,j=0
set Resstr=
call :Split %1 Snum m
call :Split %2 Snum_ n

for /l %%i in (0 1 %m%) do (
    for /l %%j in (0 1 %n%) do (
        set/a j=%%i+%%j
        set/a ResNum!j!+=!Snum%%i!*!Snum_%%j!))

set/a j+=1,flag=0
for /l %%i in (0 1 %j%) do (
      set/a ResNum%%i+=!flag!
      if !ResNum%%i! GTR 10000 (
            set/a flag=!ResNum%%i:~0,-4!
            set ResNum%%i=!ResNum%%i:~-4!) else (
               set ResNum%%i=0000!ResNum%%i!
               set ResNum%%i=!ResNum%%i:~-4!
               set/a flag=0)
      set Resstr=!ResNum%%i!!Resstr!)
for /f "delims=0 tokens=*" %%i in ("%Resstr%") do set Resstr=%%i
for /l %%i in (0 1 %j%) do set/a ResNum%%i=0

goto :eof

:Sub MaxNum MinNum
     set/a flag1=0,m=0,n=0
     call :Split %1 ok m
     call :Split %2 ok_ n
     for /l %%i in (0 1 %n%) do (
         set/a ok%%i-=!ok_%%i!-!flag1!
         if !ok%%i! lss 0 (
             set/a ok%%i+=10000
             set/a flag1=-1) else (set/a flag1=0)
         set ok%%i=0000!ok%%i!
         set ok%%i=!ok%%i:~-4!)
     if !flag1! LSS 0 (
          set/a n+=1
          set/a ok!n!+=!flag!)
     for /l %%i in (0 1 %m%) do set OKstr=!ok%%i!!OKstr!

作者: flyinspace     时间: 2007-5-2 17:47
::code by youxi01@cn-dos.net @ECHO OFF setlocal enabledelayedexpansion title 乱序数值的提取与计算 color 1f set "str1=flyi2121212t2fds654654546654654654654656521d5g615" set "str2=wo6654541s1545446ffd6551323" set/a m=0 echo 正在提取str1中的数值... echo. echo 提取出的数值有: echo. call :GetStr "%str1%" set Rnum echo --------------------------------------- set/a Resstr=1 echo 正在求取str1中各数值之积... echo. FOR /F "delims== tokens=2" %%i in ('set Rnum') do call :Multi !Resstr! %%i set num1=!Resstr! echo 计算结果为:%num1% for /l %%i in (1 1 %i%) do set Rnum%%i= set/a i=0,Resstr=1 echo --------------------------------------- echo 正在提取str2中的数值... echo. echo 提取出的数值有: echo. call :GetStr "%str2%" set Rnum echo --------------------------------------- echo 正在求取str2中各数值之积... FOR /F "delims== tokens=2" %%i in ('set Rnum') do call :Multi !Resstr! %%i set num2=%Resstr% echo 计算结果为:%num2% echo --------------------------------------- echo 正在比较大小... echo. if %num1% lss %num2% ( echo num1 比 num2 小 call :Sub %num2% %num1%) else ( echo num1 比 num2 大 call :Sub %num1% %num2%) for /f "delims=0 tokens=*" %%i in ("!OKstr!") do echo 它们的差值为:%%i pause>nul :GetStr OBJ set "str=%~1" set/a i=1 for /l %%i in (0 1 10000) do ( set "Tstr=!str:~%%i,1!" IF "!Tstr!"=="" call :Check Rnum!i! & goto :eof IF !Tstr! GEQ 0 IF !Tstr! LEQ 9 (call set Rnum!i!=%%Rnum!i!%%!Tstr!) else ( if defined Rnum!i! call :Check Rnum!i! & set/a i+=1)) goto :EOF :Check OBJ for /f "delims=0 tokens=*" %%i in ("!%1!") do set %1=%%i GOTO :EOF :Split OBJ num(i)Name CX set Rstr=%~1 if %Rstr% LEQ 10000 set "%2!%3!=%Rstr%" & goto :eof set/a %2!%3!=10000%Rstr:~-4%%%10000 set/a %3+=1 call :Split %Rstr:~0,-4% %2 %3 goto :eof :Multi set/a m=0,n=0,j=0 set Resstr= call :Split %1 Snum m call :Split %2 Snum_ n for /l %%i in (0 1 %m%) do ( for /l %%j in (0 1 %n%) do ( set/a j=%%i+%%j set/a ResNum!j!+=!Snum%%i!*!Snum_%%j!)) set/a j+=1,flag=0 for /l %%i in (0 1 %j%) do ( set/a ResNum%%i+=!flag! if !ResNum%%i! GTR 10000 ( set/a flag=!ResNum%%i:~0,-4! set ResNum%%i=!ResNum%%i:~-4!) else ( set ResNum%%i=0000!ResNum%%i! set ResNum%%i=!ResNum%%i:~-4! set/a flag=0) set Resstr=!ResNum%%i!!Resstr!) for /f "delims=0 tokens=*" %%i in ("%Resstr%") do set Resstr=%%i for /l %%i in (0 1 %j%) do set/a ResNum%%i=0 goto :eof :Sub MaxNum MinNum set/a flag1=0,m=0,n=0 call :Split %1 ok m call :Split %2 ok_ n for /l %%i in (0 1 %n%) do ( set/a ok%%i-=!ok_%%i!-!flag1! if !ok%%i! lss 0 ( set/a ok%%i+=10000 set/a flag1=-1) else (set/a flag1=0) set ok%%i=0000!ok%%i! set ok%%i=!ok%%i:~-4!) if !flag1! LSS 0 ( set/a n+=1 set/a ok!n!+=!flag!) for /l %%i in (0 1 %m%) do set OKstr=!ok%%i!!OKstr!
略略测试了一下。。发现 乘法方面做得不错。。。 但,,计算差值方面有问题。。不能正确计算出两者间的差值。。。

作者: youxi01     时间: 2007-5-2 17:50
是吗? 最好贴个错误结果出来看看,我看下错在哪里啊?

作者: youxi01     时间: 2007-5-2 18:14
TO :flyinspace 我真的没发现问题哦,你如果发现了问题,快点提出来啊?!

作者: flyinspace     时间: 2007-5-2 18:23
正在提取str1中的数值... 提取出的数值有: Rnum1=21 Rnum2=12 Rnum3=2 Rnum4=65 Rnum5=6521 Rnum6=5 Rnum7=615 --------------------------------------- 正在求取str1中各数值之积... 计算结果为:656905977000 --------------------------------------- 正在提取str2中的数值... 提取出的数值有: Rnum1=665 Rnum2=4541 Rnum3=154 Rnum4=5446 Rnum5=6551323 --------------------------------------- 正在求取str2中各数值之积... 计算结果为:16592067927276590980 --------------------------------------- 正在比较大小... num1 比 num2 大 它们的差值为:729629386020
你自己看吧。。。这个结果可能么??

作者: youxi01     时间: 2007-5-2 18:32
呵呵,知道错在哪里了。 被CMD骗了,当数字过大的时候,它自动将 数字型数据 当作 字符串。

作者: flyinspace     时间: 2007-5-2 18:39
Originally posted by youxi01 at 2007-5-2 05:32 AM: 呵呵,知道错在哪里了。 被CMD骗了,当数字过大的时候,它自动将 数字型数据 当作 字符串。
呵。期待你的代码:) 比我写的强多了。。 我的好长一段。。。而且在计算乘法方面在某种情况下还是有错误。。 (都不好意思拿出来现眼)

作者: youxi01     时间: 2007-5-2 18:42
先提示下先,可以根据位数来判断数字的大小 因为我上网不定期,说不定10天半月的都不能来了,痛哭中...

作者: flyinspace     时间: 2007-5-2 18:46
Originally posted by youxi01 at 2007-5-2 05:42 AM: 先提示下先,可以根据位数来判断数字的大小 因为我上网不定期,说不定10天半月的都不能来了,痛哭中...
呵呵,这段代码我们都可以修改了。。不过尊重原作者的缘故。。 所以才等你修改呀:) 不上网的时候,正好可以放松一下哦,以后再玩挑战系列的时候,可以事半功倍的。

作者: youxi01     时间: 2007-5-2 18:48
好,回去再想想,把代码也精简一下

作者: youxi01     时间: 2007-5-3 15:20
代码已经更新,欢迎测试。
::code by youxi01@cn-dos.net
::乱序数值的提取与计算 Ver 1.30
::解决某些大数字比较时存在的一些问题;
::解决大数字相减时,进退位错误问题。

@echo off
setlocal enabledelayedexpansion
title 乱序数值的提取与计算
color 1f
set "str1=999s999s9999s99999s99999s9999999s9999999999999s99999999999s99999999999s9999999"
set "str2=999888898d9999999999999999999dddddd999999999999999999999999999999999999"
set/a m=0
echo 正在提取str1中的数值...
echo.
echo 提取出的数值有:
echo.
call :GetStr "%str1%"
set Rnum
echo ---------------------------------------
set/a Resstr=1
echo 正在求取str1中各数值之积...
echo.
FOR /F "delims== tokens=2" %%i in ('set Rnum') do call :Multi !Resstr! %%i
set num1=!Resstr!
echo 计算结果为:%num1%
for /l %%i in (1 1 %i%) do set Rnum%%i=
set/a i=0,Resstr=1
echo ---------------------------------------
echo 正在提取str2中的数值...
echo.
echo 提取出的数值有:
echo.
call :GetStr "%str2%"
set Rnum
echo ---------------------------------------
echo 正在求取str2中各数值之积...
FOR /F "delims== tokens=2" %%i in ('set Rnum') do call :Multi !Resstr! %%i
set num2=%Resstr%
echo 计算结果为:%num2%

echo ---------------------------------------
echo 正在比较大小...
echo.
call :GetLen %num1% StrLen
call :GetLen %num2% StrLen_
set "MaxNum=num1" & set "MinNum=num2"
if !StrLen! LSS !StrLen_! (
      set "MaxNum=num2" & set "MinNum=num1") else if !StrLen! EQU !StrLen_! (
           for /l %%i in (0 1 %StrLen%) do (
               set/a ttstr=!num1:~%%i,1!,ttstr_=!num2:~%%i,1!
               if !ttstr! LSS !ttstr_! set "MaxNum=num2" & set "MinNum=num1" & GOTO :Res)) 
:Res
    echo %MaxNum% 比 %MinNum% 大
    call :Sub !%MaxNum%! !%MinNum%!
    for /f "delims=0 tokens=*" %%i in ("!OKstr!") do echo 它们的差值为:%%i
pause>nul

:GetStr OBJ
   set "str=%~1"
   set/a i=1
   for /l %%i in (0 1 1000) do (
       set "Tstr=!str:~%%i,1!"
       IF "!Tstr!"=="" call :Check Rnum!i! & goto :eof
       IF !Tstr! GEQ 0 IF !Tstr! LEQ 9 (call set Rnum!i!=%%Rnum!i!%%!Tstr!) else (
            if defined Rnum!i! call :Check Rnum!i! & set/a i+=1))
       goto :EOF
         
:Check OBJ
   for /f "delims=0 tokens=*" %%i in ("!%1!") do set %1=%%i
   GOTO :EOF

:Split OBJ num(i)Name CX
   set Rstr=%~1
   if %Rstr% LSS 10000 set "%2!%3!=%Rstr%" & goto :eof
   if "%Rstr:~-4%"=="0000" (set/a %2!%3!=0) else set/a %2!%3!=10000%Rstr:~-4%%%10000
   set/a %3+=1
   call :Split %Rstr:~0,-4% %2 %3
   goto :eof

:Multi
set/a m=0,n=0,j=0
set Resstr=
call :Split %1 Snum m
call :Split %2 Snum_ n

for /l %%i in (0 1 %m%) do (
    for /l %%j in (0 1 %n%) do (
        set/a j=%%i+%%j
        set/a ResNum!j!+=!Snum%%i!*!Snum_%%j!))

set/a j+=1,flag=0
for /l %%i in (0 1 %j%) do (
      set/a ResNum%%i+=!flag!
      if !ResNum%%i! GTR 10000 (
            set/a flag=!ResNum%%i:~0,-4!
            set ResNum%%i=!ResNum%%i:~-4!) else (
               set ResNum%%i=0000!ResNum%%i!
               set ResNum%%i=!ResNum%%i:~-4!
               set/a flag=0)
      set Resstr=!ResNum%%i!!Resstr!)
for /f "delims=0 tokens=*" %%i in ("%Resstr%") do set Resstr=%%i
for /l %%i in (0 1 %j%) do set/a ResNum%%i=0

goto :eof

:Sub MaxNum MinNum
     set/a flag1=0,m=0,n=0
     call :Split %1 ok m
     call :Split %2 ok_ n
     for /l %%i in (0 1 %n%) do (
         set/a ok%%i-=!ok_%%i!-!flag1!
         Call :Check1 ok%%i)
     if !flag1! LSS 0 (
          set/a n+=1
          for /l %%i in (!n! 1 %m%) do (
              set/a ok%%i+=!flag1!
              call :Check1 ok%%i
        )
     )
     for /l %%i in (0 1 %m%) do set OKstr=!ok%%i!!OKstr!
     goto :EOF

:GetLen OBJ Res
     set str=%~1
     for /l %%i in (0 1 10000) do (
          set tmpstr=!str:~%%i,1!
          if "!tmpstr!"=="" goto :eof
          set/a %2+=1)
     goto :EOF
         
:Check1 OBJ
        if !%1! lss 0 (
           set/a %1+=10000
           set/a flag1=-1) else set/a flag1=0
        set %1=0000!%1!
        set %1=!%1:~-4!

作者: zhoushijay     时间: 2007-5-4 21:23
天啊,51回家拿了你的问题想破头都设计不出一套算法,今天到网吧看到原来不用把最后一个数字去掉的,那应该容易一点吧,回去再想……

作者: flyinspace     时间: 2007-5-6 02:01
re youxi01 兄的代码实在漂亮。加分 re zhoushijay 努力,实在不行可以参考youxi01的代码哦:)