Board logo

标题: [挑战2] 变量的检测和计算[难度:★] [打印本页]

作者: flyinspace     时间: 2007-4-30 13:51    标题: [挑战2] 变量的检测和计算[难度:★]

set "num1=qwer/asdf2/asd34f/1234567890123456/asdf/aaaa"
set "num2=aaaaa2/23456789012345678/asdfssasd/asdaa"

目标:在上面两个条件中提取出纯数字的组合,并计算这两个数字的和,然后正确输出到屏幕上。(提取上面两个字符串只可以使用一个子程序,因为是测试的关系,只给出2个字符串的组合)

编写条件:cmd (help里包含的命令)

难点:随机的数字存在位和计算时的溢出

目标人群:有一定批处理基础的人。

注:挑战会逐渐提高难度。(大家尽量就自己会做的做出来)

编写积分奖励:3分。

完成提取任务的一分,完成计算任务的二分。。

加分不是目的。是对能力的一种肯定。

2楼正确获取了 随机的字符串,但在处理计算时问题上有点问题。

输出为科学记数法。。但要求是:输出精确数值。。(完成第一项,加一分)

[ Last edited by flyinspace on 2007-4-30 at 01:19 PM ]
作者: baomaboy     时间: 2007-4-30 14:48
由于对P一窍不通 写个VBS吧
num1="qwer/asdf2/asd34f/1234567890123456/asdf/aaaa"
num2="aaaaa2/23456789012345678/asdfssasd/asdaa"
numarr=split(num1&"/"&num2,"/")
For i=0 To UBound(numarr)
if IsNumeric(numarr(i)) then
num=num+CDbl(numarr(i))
end if
Next
msgbox num
msgbox FormatNumber(num,0,,,0)
[ Last edited by baomaboy on 2007-4-30 at 04:37 PM ]
作者: flyinspace     时间: 2007-4-30 15:18


  Quote:
Originally posted by baomaboy at 2007-4-30 01:48 AM:
由于对P一窍不通 写个VBS吧
[code]
num1="qwer/asdf2/asd34f/1234567890123456/asdf/aaaa"
num2="aaaaa2/23456789012345678/asdfssasd/asdaa"
numarr=split(num1&"/"&num2,"/")
For i=0 To UBound(numarr)
if IsNumeric(numarr(i)) then
num=num+CDbl(numarr(i))
end if
Next
msgbox num

挑战失败:
原因见附件:

我们要求正确输出 结果。

[ Last edited by flyinspace on 2007-4-30 at 02:35 AM ]
附件 1: 1.JPG (2007-4-30 15:31, 3.91 K, 下载附件所需积分 1点 ,下载次数: 2)



作者: zh159     时间: 2007-4-30 15:41
楼上的,二楼结果是正确的,E+16是科学计数的写法代表N*(1后面有16个零)
24691356902469134=2.46913569024691*10000000000000000=2.46913569024691E+16
作者: flyinspace     时间: 2007-4-30 15:46
不好意思,我也知道他的结果正确。。。。

但我们的要求是 :
         输出:24691356902469134
这个结果,而不是2.46913569024691E+16 这个结果。。

这个算我没有说清楚。。。。

若我们的数字再变化一下呢??  有 30位呢?

我们要求的是精确。。。呵呵。。

最后谢谢 zh159的指出。
作者: baomaboy     时间: 2007-4-30 16:35


  Quote:
Originally posted by flyinspace at 2007-4-30 15:46:
不好意思,我也知道他的结果正确。。。。

但我们的要求是 :
         输出:24691356902469134
这个结果,而不是2.46913569024691E+16 这个结果。。

这个 ...

那就格式化一下吧:
msgbox FormatNumber(num,0,,,0)

不过估计你那最后两位34没人能得到吧,早几年在Excel中就发现超过15位后全显示0,也许是微软觉得15位已经够用了限制了吧,呵呵,开玩笑的,反正我是用不到15位不深究了,有人知道指点下。

[ Last edited by baomaboy on 2007-4-30 at 04:51 PM ]
作者: digger     时间: 2007-4-30 20:15
计算两数的和这个话题论坛里曾经有过专题讨论,在精华帖里,有难度啊。
作者: youxi01     时间: 2007-4-30 20:55
我曾经写过 大数字的 计算(乘法)的,计算数字在 100 位以内。

还有,看2F的代码 似乎 两个字符串 只是其中有一项目 是数字哦!(就是说 没有其它的特殊情况罗,比如:有两项数字又该怎么处理等?)

[ Last edited by youxi01 on 2007-4-30 at 08:56 PM ]
作者: youxi01     时间: 2007-4-30 21:26
提供一下思路:(因为马上要工作,就不能给出详细代码了。同时,因为搬家的原因,短期内要上不了网,所以也可能暂离联盟。)
1、关于各字符段的提取,昨天的挑战一就有相关代码。
2、提取出的各字符段,是否是数字相关判断的问题。此问题解决办法有三:
1>利用set/a 的特殊性,此办法不严谨,无法防止字符段恰好为0的情况。
2>利用findstr+正则,比较精确,但效率不高。
3>个人比较推荐的办法:拿字母(包括汉字)直接和数字比较大小,如果,某字符段是纯数字,它就一定比 a 小。缺点:无法处理特殊字符。
3、有关特大数字的计算。我们可以采取分段计算的办法,已经有相关讨论,我曾经也写过相关代码,在此不作赘述。
作者: flyinspace     时间: 2007-4-30 22:23    标题: 给出 计算 大数字的演示,提取好象大家都会?

@echo off & setlocal EnableDelayedExpansion
        set "a=123456789012485642424543456"
        set "b=234567890000000000000005678"
        call :GetLen "%a%"
        set "Len1=%Len%"
        call :GetLen "%b%"
        set "Len2=%Len%"
        set "s="
        set "bit=0"
        set "count=0"
:recompute
        set /a "count+=1"
        if %Len1% GEQ 9 (
                set "str1=%a:~-9%
                set "a=%a:~0,-9%"
                set /a "Len1-=9"
                ) else (
                set "str1=%a%"
                set "a=0"
                )
        if %Len2% GEQ 9 (
                set "str2=%b:~-9%"
                set "b=%b:~0,-9%
                set /a "Len2-=9"
                ) else (
                set "str2=%b%"
                set "b=0"
                )
call :formatstr %str1%
        set "str1=%xxx%
call :formatstr %str2%
        set "str2=%xxx%
        set /a "num=!str1!+!str2!+!bit!"
        call :GetLen "%num%"
        if '%Len% GTR 9' (
                set "bit=%num:~0,1%"
                set "num=%num:~-9%"
                )
        set "s=%num%%s%"
        echo [%count%]: %str1%[%Len1%]+%str2%[%Len2%]=%s%
        if "%a%"=="0" (
                if "%b%" == "0" (
                        goto :END
                )
        )
goto :recompute


:formatstr _str_
        set "xxx=%~1"
:reformat
        set "lll=9"
        if "%xxx:~0,1%"=="0" (
                set "xxx=!xxx:~1,%lll%!
                set /a "lll-=1"
                goto :reformat
                )
        goto :EOF

:GetLen
        set "string=%~1"
        for /l %%i in (0,1,255) do (
                if "!string:~%%i,1!"=="" (
                        set "Len=%%i"
                        goto :EOF
                        )
                )
        goto :EOF
:END
echo ——————————————————————————
echo 最后答案为:%s%
echo ——————————————————————————
echo 程序演示结束,任意键退出 & pause>nul

[ Last edited by flyinspace on 2007-4-30 at 04:29 PM ]
作者: zhoushijay     时间: 2007-5-1 00:58
num1="qwer/asdf2/asd34f/1234567890123456/asdf/aaaa"
num2="aaaaa2/23456789012345678/asdfssasd/asdaa"
len1=len(num1)
len2=len(num2)


for i=1 to len1
nu1=mid (num1,i,1)

on error resume next
a=int(nu1)
if err.number=0 then
b=b&a
end if
next

for a=1 to len2
nu2=mid (num2,a,1)

on error resume next
d=int(nu2)
if err.number=0 then
s=s&d

end if
next
s=int(s)
b=int(b)

he=s+b

msgbox(he)正确的答案应该是2564691356902469134,我用计算器算了2遍

[ Last edited by zhoushijay on 2007-4-30 at 04:53 PM ]
作者: baomaboy     时间: 2007-5-1 04:18


  Quote:
Originally posted by youxi01 at 2007-4-30 20:55:
我曾经写过 大数字的 计算(乘法)的,计算数字在 100 位以内。

还有,看2F的代码 似乎 两个字符串 只是其中有一项目 是数字哦!(就是说 没有其 ...

当数值型字串与数值在一起做运算时,数值型字串被当作数值
作者: flyinspace     时间: 2007-5-1 05:01


  Quote:
Originally posted by zhoushijay at 2007-4-30 11:58 AM:
nu1=mid (num1,i,1)

on error resume next
a=int(nu1)
if err.number=0 then
b=b&a
end if
next

for a=1 to len2
nu2=mid (num2,a,1)

on error resume next
d=int(nu2)
if err.number=0 then
s=s&d

end if
next
s=int(s)
b=int(b)

he=s+b
msgbox(he)
正确的答案应该是2564691356902469134,我用计算器算了2遍

=1234567890123456
23456789012345678+
--------------------------------
24691356902469134

怎么比也没有算错啊??

怎么会是
2564691356902469134呢?

[ Last edited by flyinspace on 2007-4-30 at 04:10 PM ]
作者: bjsh     时间: 2007-5-1 05:16
抽出了点时间 写了这个..
结果为:24691356902469134

  Quote:

  1. @echo off & setlocal enabledelayedexpansion
  2. set "num1=qwer/asdf2/asd34f/1234567890123456/asdf/aaaa"
  3. set "num2=aaaaa2/23456789012345678/asdfssasd/asdaa"
  4. set "num1=%num1:/= %" & call :get_number !num1! & set "num1=!t!"
  5. set "num2=%num2:/= %" & call :get_number !num2! & set "num2=!t!"
  6. set "result="
  7. :c_loop
  8. set /a x=%num1:~-8%
  9. set /a y=%num2:~-8%
  10. set /a z=%x%+%y%
  11. if defined flag set /a z=%z%+%flag%
  12. set "flag=%z:~0,-8%" >>nul 2>>nul && set "z=%z:~-8%"
  13. set "num1=%num1:~0,-8%"
  14. set "num2=%num2:~0,-8%"
  15. set "result=%z%%result%"
  16. if not defined num1 if not defined num2 set "result=%flag%%result%" & goto :show
  17. if not defined num1 set /a num1=0
  18. if not defined num2 set /a num2=0
  19. goto c_loop
  20. :show
  21. echo %result% & pause & goto :eof
  22. :get_number
  23. :loop
  24. echo %1 >>tmp.txt & shift
  25. if not "%1"=="" goto :loop
  26. for /f %%a in ('findstr /r "^[0-9]" tmp.txt') do set "t=%%a"
  27. del tmp.txt
         BJSH发表于:  2007-04-30  16:04


作者: zh159     时间: 2007-5-1 05:17


  Quote:
Originally posted by zhoushijay at 2007-4-30 11:58:
nu1=mid (num1,i,1)

on error resume next
a=int(nu1)
if err.number=0 then
b=b&a
end if
next

for a=1 to len2
nu2=mid (num2,a,1)

on error resume next
d=int(nu2)
if err.number=0 then
s=s&d

end if
next
s=int(s)
b=int(b)

he=s+b
msgbox(he)
正确的答案应该是2564691356902469134,我用计算器算了2遍

16位数+17位数怎么也不可能得出19位数啊?

   1234567890123456
 +23456789012345678
--------------------------------------
 =24691356902469134
=================
  2564691356902469134
作者: flyinspace     时间: 2007-5-1 05:35


  Quote:
Originally posted by bjsh at 2007-4-30 04:16 PM:
抽出了点时间 写了这个..
结果为:24691356902469134

不错,但会产生临时文件。

其实有办法不产生临时文件的。。youxia01 给了我们最好的提示:)
作者: bjsh     时间: 2007-5-1 05:44
本来也不想产生临时文件;

本来想把/替换为alt+13;

不过没有实现我的想法;真想去debug看看;

无奈时间比较紧.;

就写了下来..
作者: zhoushijay     时间: 2007-5-1 05:50
set "num1=qwer/asdf2/asd34f/1234567890123456/asdf/aaaa"
set "num2=aaaaa2/23456789012345678/asdfssasd/asdaa"

这2个数应该是
  2341234567890123456
+  223456789012345678   
-----------------------------------------
2564691356902469134
这样的吧,前面字母里还夹杂着数字呢

[ Last edited by zhoushijay on 2007-4-30 at 04:52 PM ]
作者: flyinspace     时间: 2007-5-1 06:07


  Quote:
Originally posted by zhoushijay at 2007-4-30 04:50 PM:
set "num1=qwer/asdf2/asd34f/1234567890123456/asdf/aaaa"
set "num2=aaaaa2/23456789012345678/asdfssasd/asdaa"

这2个数应该是
  2341234567890123456
+  22345678901234567 ...

噢。我们只要纯数字的那一组组合呀。。
作者: lxmxn     时间: 2007-5-1 06:20


  Quote:
Originally posted by bjsh at 2007-4-30 16:44:
本来也不想产生临时文件;

本来想把/替换为alt+13;

不过没有实现我的想法;真想去debug看看;

无奈时间比较紧.;

就写了下来..

要把/替换成换行,可以参考一下这个:
@echo off&Setlocal EnableDelayedExpansion
for /f "delims=" %%a in (1.txt) do (
        set str=%%a
        set str=!str:/=$_!
        exit|cmd/kprompt !str!>>new_.txt
)
start new_.txt

作者: everest79     时间: 2007-5-1 06:28
我原来写过的一个大数加法,根据要求改了一下
@ECHO OFF 2>nul 3>nul&setlocal enabledelayedexpansion
set "num1=qwer/asdf2/asd34f/1234567890123456/asdf/aaaa"
set "num2=aaaaa2/23456789012345678/asdfssasd/asdaa"
set num=%num1:/= % %num2:/= %
for %%i in (%num%) do echo %%i|findstr /b /e [0-9]*[0-9]&&SET Z=/0%%i !z!
call :next %z%&&goto :eof
:next
set A=%~1&set B=%~2
:ADD
SET/AX-=1
CALL SET/AT1=%%A:~%X%,1%%+%%B:~%X%,1%%||(
ECHO %T3%%C%&&PAUSE&&GOTO :EOF)
CALL SET T3=%%A:~2,%X%%%%%B:~2,%X%%%
SET/A1/T2&&SET/AT1=T1+1
SET/AT2=1/(T1/10)||SET T2=0
SET C=%T1:~-1%%C%
GOTO ADD

作者: flyinspace     时间: 2007-5-1 06:38
SET/A1/T2&&SET/AT1=T1+1
SET/AT2=1/(T1/10)||SET T2=0
这个有点不明白??

SET/A1/T2 && SET/AT1=T1+1

event79兄可以解释一下么?
作者: everest79     时间: 2007-5-1 06:47
这个是按字符位由右向左递增进行个位数相加

SET/A1/T2&&SET/AT1=T1+1  //set /a 1/t2这个来判断t2(t2为上一循环进位)是否为零,若不是,将当前结果t1加一
SET/AT2=1/(T1/10)||SET T2=0  //set /a t2=1/(t1/10)这个判断当前循环结果(t1)是否大于10,若大于十,t2将被赋值为一(下一循环上一步),若小于十,则将进位t2置为零
作者: flyinspace     时间: 2007-5-1 06:56


  Quote:
Originally posted by everest79 at 2007-4-30 05:47 PM:
这个是按字符位由右向左递增进行个位数相加

SET/A1/T2&&SET/AT1=T1+1  //set /a 1/t2这个来判断t2(t2为上一循环进位)是否为零,若不是,将当前结果t1加一
SET/AT2=1/(T1/10)||SET T2=0  //set /a t2=1/(t1/10)这个判断当前循环结果(t1)是否大于10,若大于十,t2将被赋值为一(下一循环上一步),若小于十,则将进位t2置为零


谢谢兄的说明,我理解了这句话的含义!

新的问题是: 为什么要 set/a1/t2&&set/at1=t1+1
      加这个 / 有什么用?

按你的说法:这句话相当于>
       set /a xxx= 1 / t2
       利用 set /a 的特殊性: 
        若 xxx 小于1,则 xxx= 0
       为 0 满足条件。则 t2 += 1

又学到了一招。。有点类似 set /p 的感觉?且不要=号。
作者: everest79     时间: 2007-5-1 07:00
set /a a=1+1可以缩写为set/aa=1+1,那时我刚打别人实例上看到这个,所以就这么给写上了,不算好的书写习惯
作者: flyinspace     时间: 2007-5-1 07:06


  Quote:
Originally posted by everest79 at 2007-4-30 06:00 PM:
set /a a=1+1可以缩写为set/aa=1+1,那时我刚打别人实例上看到这个,所以就这么给写上了,不算好的书写习惯

set /a a=1/a 也相当于 set /a1/a??
作者: everest79     时间: 2007-5-1 07:59
不是的
set /a a=1/a是计算赋值
set /a 1/a只是计算
作者: youxi01     时间: 2007-5-2 17:35
21F的代码似乎有点点问题,要继续修改下:
测试如下:
19586
453
10039
请按任意键继续. . .
自己也发一段不成熟的代码(如果段数较多时,效率较高):
::code by youxi01@cn-dos.net
@echo off & setlocal enabledelayedexpansion
set "str1=qwer/asdf2/asd34f/13546641654546546654654654144553098785546154/asdf/aaaa"
set "str2=aaaaa2/453216543225443263845482842643/asdfssasd/asdaa"
call :GetNum "%str1%" num1
call :GetNum "%str2%" num2
call :Split %num1%
set/a Mnum=%num%,num=0,flag=0
call :Split %num2%
if %Mnum% LSS %num% set/a Mnum=%num%
set/a Mnum_=%Mnum%-1
for /l %%i in (1 1 %Mnum_%) do (
   set/a Rnum%%i+=!flag!
   if !Rnum%%i! GTR 10000 set/a flag=1
   set Rnum%%i=000!Rnum%%i!
   set Rnum%%i=!Rnum%%i:~-4!
   set Rstr=!Rnum%%i!!Rstr!)
set/a Rnum%Mnum%+=%flag%
echo !Rnum%Mnum%!!Rstr!
pause>nul
:GetNum OBJ Res
   for /f "delims=/ tokens=1,*" %%i in ("%~1") do (
       if %%i LSS a set %2=%%i & goto :eof
       call :GetNum "%%j" %2
     ) & goto :eof
:Split OBJ
    set str=%~1
    set/a num+=1
    if %str% LSS 10000 set/a Rnum%num%+=%str% & goto :eof
    set/a Rnum%num%+=10000%str:~-4%%%10000
    set str=%str:~0,-4%
    call :Split "%str%"

作者: flyinspace     时间: 2007-5-2 19:02


  Quote:
Originally posted by youxi01 at 2007-5-2 04:35 AM:
21F的代码似乎有点点问题,要继续修改下:
测试如下:
19586
453
10039
请按任意键继续. . .
自己也发一段不成熟的代码(如果段数较多 ...

代码看得好累。。

有没有算法??

给个提示?
作者: youxi01     时间: 2007-5-3 15:17
::code by youxi01@cn-dos.net
@echo off & setlocal enabledelayedexpansion

set "str1=qwer/asdf2/asd34f/13546641/asdf/aaaa"
set "str2=aaaaa2/45321/asdfssasd/asdaa"

call :GetNum "%str1%" num1
call :GetNum "%str2%" num2

call :Split %num1%

REM Mnum保存结果的段数(用来接受最大的段数);
REM 将num的值重新归0,用来继续调用"函数"
REM flag为进位标记,如果为1,则下段数字加1;这里为初始值,设置为1。
set/a Mnum=%num%,num=0,flag=0

call :Split %num2%
if %Mnum% LSS %num% set/a Mnum=%num%
set/a Mnum_=%Mnum%-1

for /l %%i in (1 1 %Mnum_%) do (
   set/a Rnum%%i+=!flag!
   if !Rnum%%i! GTR 10000 set/a flag=1

   REM 在前面加000,是为了补齐数字的,防止333这样位数不足4位的数字。
   set Rnum%%i=000!Rnum%%i!

   set Rnum%%i=!Rnum%%i:~-4!
   set Rstr=!Rnum%%i!!Rstr!)

set/a Rnum%Mnum%+=%flag%
echo !Rnum%Mnum%!!Rstr!

pause>nul

:GetNum OBJ Res
   for /f "delims=/ tokens=1,*" %%i in ("%~1") do (

       REM 利用是否大于a,来检测是否是数字,如果是,则一定小于a(不管是多少位的数字)
       REM 如果检测到数字,则退出。
       if %%i LSS a set %2=%%i & goto :eof

       REM 循环检测;
       call :GetNum "%%j" %2
     ) & goto :eof

:Split OBJ
    set str=%~1
    set/a num+=1

    REM 如果,切割后的数字小于10000,则设置自身的值为原值加上该数字,并退出;
    if %str% LSS 10000 set/a Rnum%num%+=%str% & goto :eof

    REM 利用willsort的办法,屏除类似0001给利用set/a计算带来的错误;
    set/a Rnum%num%+=10000%str:~-4%%%10000

    set str=%str:~0,-4%
    call :Split "%str%"
作者: 111ab     时间: 2007-5-10 13:35


  Quote:
Originally posted by bjsh at 2007-5-1 05:16 AM:
抽出了点时间 写了这个..
结果为:24691356902469134

bjsh兄:
     无意间看到了你的帖子,被你的代码折服了。花了一天多时间拜读了一下你的代码,刚弄懂提取数字字段那部分,我是菜鸟,别笑话我,哈。有点问题想请教。
     感觉你的 findstr 的正则表达式对字串类似"12345adfadfds45156"(头尾均为数字,但中间为字符)的情况也能匹配。我想改成这样地:
                          findstr  "^[0-9][0-9]*$"  tmp.txt
你的findstr中有个参数是 /r , 我在命令行查看findstr的帮助的时候没看到有这个参数,就对加 /r 和不加 /r两种情况分别试了一下,没看出什么区别,那个 /r 是做什么用地呢?

注:正则表达式 "^[0-9][0-9]*$" 并不能匹配字串类似"123457684    "的情况,所以:get_number段中代码要做一下小小改动,我的建议如下:
原代码:    echo %1 >>tmp.txt & shift   
修改后:    echo %1>>tmp.txt& shift     ::注意该处%1后和.txt后均不能有空格,否则空格会被输入到.txt中,影响正则表达式的匹配。
或改成:    echo %1>>tmp.txt
                shift
作者: flyinspace     时间: 2007-5-10 17:24


  Quote:
Originally posted by 111ab at 2007-5-10 01:35 PM:

bjsh兄:
     无意间看到了你的帖子,被你的代码折服了。花了一天多时间拜读了一下你的代码,刚弄懂提取数字字段那部分,我是菜鸟,别笑话我, ...

我对正则表达式还是不太明白。。刚刚接触vbs。。

但兄可以仔细看看 findstr /?

里面有说明: /r 表示使用一般表达式。而根据下面对一般表达式的描叙,应该是属于正则表达式范畴。
作者: bjsh     时间: 2007-6-6 10:55
to 111ab

  Quote:
感觉你的 findstr 的正则表达式对字串类似"12345adfadfds45156"(头尾均为数字,但中间为字符)的情况也能匹配。我想改成这样地:
                          findstr  "^[0-9][0-9]*$"  tmp.txt



  Quote:
注:正则表达式 "^[0-9][0-9]*$" 并不能匹配字串类似"123457684    "的情况,所以:get_number段中代码要做一下小小改动,我的建议如下:
原代码:    echo %1 >>tmp.txt & shift   
修改后:    echo %1>>tmp.txt& shift     ::注意该处%1后和.txt后均不能有空格,否则空格会被输入到.txt中,影响正则表达式的匹配。
或改成:    echo %1>>tmp.txt
                shift

感谢兄的指点;
兄的建议 很有道理
作者: 26933062     时间: 2007-8-15 19:12

:: 向各位高手学习的同时,自己也写了个,没什么技术可言。
:: 不过好像就楼主的要求,能够达到目的
:: 得到的结果是 24691356902469134
:: 特点:
::     不限于数字的大小,只要是求和的都可以
:: 思路:
::    直接加最后一位数,再加进位的数,再将原数舍弃最后一位,如此循环,直至结果.


@echo off & setlocal enabledelayedexpansion
set "num1=qwer/2asdf2/asd34f/1234567890123456/asdf/aaaa"
set "num2=aaaaa2/23456789012345678/asdfssasd/asdaa"

set "num1=%num1:/= %"&set "num2=%num2:/= %"&set b=1
for %%i in (%num1% %num2%) do (
echo %%i|findstr "^[0-9]*$">nul&&set num!b!=%%i&&set /a b+=1
)
set jin=0

:loop
set /a a=%num1:~-1%+%num2:~-1%+%jin%
set jieguo=%a:~-1%%jieguo%
set a=0%a%
set jin=%a:~-2,1%
set num1=%num1:~0,-1%
set num2=%num2:~0,-1%
if "%num1%"=="" set /a zz=%num2%+%jin%&goto lis
if "%num2%"=="" set /a zz=%num1%+%jin%&goto lis
goto loop

:lis
if "%zz%"=="0" set zz=
echo.&echo   结果:%zz%%jieguo%
echo.&pause
[ Last edited by 26933062 on 2007-8-15 at 07:51 PM ]
作者: youxi01     时间: 2007-8-15 20:58
又回到这个问题了。
刚刚想到一个“补位”的方法来实现加法,从而避开所有的if检查,而且程序主要部分都是在for中运行,避开了goto的使用,从而使效率大大提高(特别是针对特大数字)。所给程序代码支持 200 位以内数字的加法。
::code by youxi01@cn-dos.net
@echo off&setlocal enabledelayedexpansion
set "str1=qwer/asdf2/asd34f/123456789012345665644654456454665446565446544665446546545644565465464646546544654546654654465654465654665465465465446565446564/asdf/aaaa"
set "str2=aaaaa2/23456789012345678654466544466544641125654456455464654546654465654465446554665445454654544545654/asdfssasd/asdaa"
call :GetNum %str1% num1
call :GetNum %str2% num2
call :lineup num1
call :lineup num2
set/a flag=0
for /l %%i in (2 1 199) do (
set/a var=!num1:~-%%i,1!+!num2:~-%%i,1!+!flag!
set var=0!var!
set flag=!var:~-2,1!
set str=!var:~-1!!str!
)
for /f "delims=0 tokens=*" %%i in ("!str!") do echo %%i
pause>nul
:GetNum OBJ Res
   for /f "delims=/ tokens=1,*" %%i in ("%~1") do (
       if %%i LSS a set %2=%%i & goto :eof
       call :GetNum "%%j" %2
     ) & goto :eof
:lineup obj
    for /l %%i in (1 1 200) do set %1=0!%1!
    call set %1=!%1:~-200!
[ Last edited by youxi01 on 2007-8-15 at 09:07 PM ]
作者: knoppix7     时间: 2007-8-15 22:31
高手看看这个行不??


@echo off
set "num1=qwer/asdf2/asd34f/1234567890123456/asdf/aaaa"
set "num2=aaaaa2/23456789012345678/asdfssasd/asdaa"
SETLOCAL ENABLEDELAYEDEXPANSION
set tester=500
:main1
FOR /F "tokens=1,2* delims=/" %%i in ("%num1%") do (
set NTC=
set RUS=
set NTC=%%i
set /a RUS=%tester%+!NTC!>>nul>>nul
if !ERRORLEVEL!==9168 set shuzi1=!NTC!
set num1=%%j/%%k
goto main1
)
cls
:main2
FOR /F "tokens=1,2* delims=/" %%a in ("%num2%") do (
set NTC=
set RUS=
set NTC=%%a
set /a RUS=%tester%+!NTC!>>nul>>nul
if !ERRORLEVEL!==9168 set shuzi2=!NTC!
set num2=%%b/%%c
goto main2
)
cls
echo !shuzi1!
echo !shuzi2!
pause
作者: 26933062     时间: 2007-8-16 20:05

:: 写了个补位的,如你所说,全局没有一个goto和if
:: 但是效率好像没见有什么提高啊?

@echo off & setlocal enabledelayedexpansion
set "num1=qwer/2asdf2/asd34f/1234567890123456/asdf/aaaa"
set "num2=aaaaa2/23456789012345678/asdfssasd/asdaa"

set "num1=%num1:/= %"&set "num2=%num2:/= %"&set b=1
for %%i in (%num1% %num2%) do (
echo %%i|findstr "^[0-9]*$">nul&&set num!b!=%%i&&set /a b+=1
)
echo !num1! + !num2!
for /l %%i in (1 1 200) do (
set num1=0!num1!
set num2=0!num2!
)
set num1=!num1:~-200!&set num2=!num2:~-200!

set jin=0
for /l %%i in (-1 -1 -200) do (
set /a a=!num1:~%%i,1!+!num2:~%%i,1!+!jin!
set jie=!a:~-1!!jie!
set a=0!a!
set jin=!a:~-2,1!
)
for /f "tokens=* delims=0" %%i in ("!jie!") do echo.&echo %%i
echo.&pause

作者: youxi01     时间: 2007-8-16 20:31
哦,你试下特大数字就知道了
作者: knoppix7     时间: 2007-8-16 20:37
LZ给的数字很长。
直接用set运算会报错。ERROELV为9168
那样只要只要检测到ERRORLEVEL==9168不就可以了?