Board logo

标题: [共同参与][挑战思路][批处理处理浮点运算] [打印本页]

作者: redtek     时间: 2006-10-4 04:10    标题: [共同参与][挑战思路][批处理处理浮点运算]

) 此贴为抛砖引玉,大家扩展思路,互动式共同参与批处理学习~:)

) [用DOS内部命令计算两个浮点数的和]

  例如: Sum.Bat   12.99    438.76
  结果: 451.75

  规则: 负数不考虑
      有可能人为故意或无意输入的非数字等错误暂不考虑
      只能使用DOS内部命令(无DOS版本限制),外部命令禁止使用。
      只考虑计算%1与%2所出现的两个浮点数相加,更多的浮点相加暂不考虑。
      允许数字出现的格式:  0.91 0.10  2.12 1092.90
      暂不允许出现的格式: .91  .9   
      (小数精度:小数点儿后两位)

  目的: 拓展思路、增加批处理兴趣、增加大家互动学习亲自动手玩、
      通过我们大家不断的交互让批处理的使用让每个人都能参与共同进步:)

  方向: 这只是其中一个内容,更多的内容需要网友们共同发现、版主支持:)
      大家可以用任何异想天开的任何想法实现上面问题~:)


  为什么要出现此贴: 只有互动每个人都参与,自己的水平才能提高更快。
            将遇到问题时才问、平时不主动学习批处理的方式变成大家主动一步一步共同提高:)


  奖励: 优秀的解题与不同思路的观点解题,由版主象神一样的指导、示范,
      然后给大家加分奖励以示激励~:)

  其它: 等待大家有更好想法和非常实用的互动学习与应用的题目,大家一起参与:)
===================================
作者: electronixtar     时间: 2006-10-4 04:20

@echo off
echo wscript.echo CDbl(WScript.Arguments(0))+CDbl(WScript.Arguments(1))> tmp.vbe
cscript //noLogo tmp.vbe %1 %2
del tmp.vbe
^_^
作者: redtek     时间: 2006-10-4 04:31


  Quote:
Originally posted by electronixtar at 2006-10-4 04:20:
@echo off
echo wscript.echo CDbl(WScript.Arguments(0))+CDbl(WScript.Arguments(1))> tmp.vbe
cscript //noLogo tmp.vbe %1 %2
del tmp.vbe
^_^

精彩~~ 加了6分~:)
C:\TEMP>a.bat  12.99  438.76
451.75

作者: pengfei     时间: 2006-10-4 04:47
本楼第一段的代码为最新修改的. 功能更加强大, 欢迎大家测试...
整数浮点数分段运算代码:
一般情况下整数位最多可运算9位数, 小数位最多可运算9位数.
小数位整数位加起来最多可运算18位数.
否则会溢出或为无效数字...

该脚本的功能:
1.  可以运算任何实型数值.
2.  有判断错误输入的功能. 如运算数中存在非法字符或当字符位数超过脚本的运算范围时会提示你重新输入.
3.  解决了进制错误的问题.
4.  运算结果格式输出.

@echo off
if not %1*==* set num1=%1 & set num2=%2 & goto jmp
:input
cls
set num1=
set /p num1=input primary number:
set num2=
set /p num2=input number two number:
:jmp
echo %num1% | find "." >nul || set num1=%num1%.0
echo %num2% | find "." >nul || set num2=%num2%.0
if "%num1:~-1%"=="." set num1=%num1%0
if "%num2:~-1%"=="." set num2=%num2%0
if "%num1:~0,1%"=="." set num1=0%num1%
if "%num2:~0,1%"=="." set num2=0%num2%
set num=0
setlocal enabledelayedexpansion
for %%a in (%num1% %num2%) do (
    set /a num+=1
    for /f "tokens=1,2 delims=." %%i in ("%%a") do (
        if "!num!"=="1" (set one=%%i) else (set one_=%%i)
        if "!num!"=="1" (set two=%%j) else (set two_=%%j)
    )
)
call :omit %one%
set one=%want%
call :omit %one_%
set one_=%want%
call :raze %two%
set two=%want_%
call :raze %two_%
set two_=%want_%
call :go %one%
set countx=%wish%
call :go %one_%
set countx_=%wish%
if "%two%"=="" set two=0
if "%two_%"=="" set two_=0
call :go %two%
set county=%wish%
call :go %two_%
set county_=%wish%
if %countx% gtr 9 goto error
if %countx_% gtr 9 goto error
set after=0
set front=
if %county% lss %county_% (
    set count=%county_%
    set /a result=%county_%-%county%
    call :fine !result! %two%
    set two=!incept!
) else (
    set count=%county%
    set /a result=%county%-%county_%
    call :fine !result! %two_%
    set two_=!incept!
)
call :omit %two%
set two=%want%
call :omit %two_%
set two_=%want%
call :go %two%
set county=%wish%
call :go %two_%
set county_=%wish%
if %county% gtr 9 goto error
if %county_% gtr 9 goto error
if "%one%"=="" set one=0
if "%one_%"=="" set one_=0
if "%two%"=="" set two=0
if "%two_%"=="" set two_=0
set /a decimal=%two%+%two_%
set carry=0!decimal:~0,-%count%!
set decimal=!decimal:~-%count%!
set refer=%decimal%
call :go %refer%
set countz=%wish%
set /a spare=%count%-%countz%
set after=
set front=0
call :fine %spare% %decimal%
set decimal=%incept%
set /a integer=%one%+%one_%+%carry%
set dot=.
call :raze %decimal%
set decimal=%want_%
if "%decimal%"=="" set dot=
cls
echo ============
echo 运算结果!
echo ============
echo.
echo %num1%+%num2%=%integer%%dot%%decimal%
pause >nul
goto :eof

:go
set remove=%1@
set wish=0
:go_
if not "!remove:~0,1!"=="@" (
    set fault=1
    for /l %%c in (0,1,9) do (
        if "!remove:~0,1!"=="%%c" (
            set /a wish+=1
            set remove=!remove:~1!
            set fault=2
            goto go_
        )
    )
    if "!fault!"=="1" goto error
    goto go_
)
goto :eof
:fine
set take=%1
set incept=%2
:fine_
if not "%take%"=="0" (
    set /a take-=1
    set incept=%front%!incept!%after%
    goto fine_
)
goto :eof
:omit
set want=%1
:omit_
if "%want:~0,1%"=="0" (
    set want=%want:~1%
    goto omit_
)
goto :eof
:raze
set want_=%1
:raze_
if "!want_:~-1!"=="0" (
    set want_=!want_:~0,-1!
    goto raze_
)
goto :eof

:error
cls
echo ========================================================
echo.
echo          对不起, 你的输入存在下面两种错误:
echo.
echo          1.  输入了除阿拉伯数字外的非法字符.
echo.
echo          2.  整数或小数位数超过了9位.
echo.
echo ========================================================
echo.
echo.
echo 按任意键重新输入...
pause >nul
goto input
下面一段也是通用的, 但小数只能运算8位数, 且没有判断错误输入和判断输入的数值是否符合要求的功能.
整数浮点数分段运算代码:
整数位最多可运算9位数, 小数位最多可运算8位数.
小数位整数位加起来最多可运算17位数.
否则会溢出或为无效数字...

可以运算任何类型的数值, 浮点型数值已不受位数限制.
解决了小数第一位为零且后面跟8或9的数字会出现进制错误的问题.
运算结果格式输出!

此段代码已经通用. 欢迎大家测试...

@echo off
set /p number1=请输入运算数一:
set /p number2=请输入运算数二:
echo %number1% | find "." >nul || set number1=%number1%.0
echo %number2% | find "." >nul || set number2=%number2%.0
if "%number1:~-1%"=="." set number1=%number1%0
if "%number2:~-1%"=="." set number2=%number2%0
if "%number1:~0,1%"=="." set number1=0%number1%
if "%number2:~0,1%"=="." set number2=0%number2%
setlocal enabledelayedexpansion
for %%a in (%number1% %number2%) do (
    set /a num+=1
    for /f "tokens=1,2 delims=." %%i in ("%%a") do (
        if "!num!"=="1" (set one=%%i) else (set one_=%%i)
        if "!num!"=="1" (set two=%%j) else (set two_=%%j)
    )
)
call :omit %one%
set one=%want%
call :omit %one_%
set one_=%want%
call :go %two%
set count=%wish%
call :go %two_%
set count_=%wish%
if %count% lss %count_% (
    set /a result=%count_%-%count%
    call :fine !result! %two%
    set two=!incept!
) else (
    set /a result=%count%-%count_%
    call :fine !result! %two_%
    set two_=!incept!
)
if "%one%"=="" set one=0
if "%one_%"=="" set one_=0
set /a integer=%one%+%one_%
set /a decimal=1%two%+1%two_%
if "%decimal:~0,1%"=="2" (
    set decimal=%decimal:~1%
) else (
    set decimal=%decimal:~1%
    set /a integer=%integer%+1
)
:raze
if "!decimal:~-1!"=="0" (
    set decimal=!decimal:~0,-1!
    goto raze
)
if "%decimal%"=="" (
    set dot=
) else (
    set dot=.
)
echo %integer%%dot%%decimal%
pause
exit

:go
set remove=%1
set wish=0
:go_
if not "!remove:~0,1!"=="~" (
    for /l %%c in (0,1,9) do (
        if "!remove:~0,1!"=="%%c" (
            set /a wish+=1
            set remove=!remove:~1!
            goto go_
        )
    )
)
goto :eof
:fine
set take=%1
set incept=%2
:fine_
if not "%take%"=="0" (
    set /a take-=1
    set incept=!incept!0
    goto fine_
)
goto :eof
:omit
set want=%1
:again
if "%want:~0,1%"=="0" (
    set want=%want:~1%
    goto again
)
goto :eof
相关问题讨论: 关于数值运算时的进制问题!

[ Last edited by pengfei on 2006-10-9 at 05:01 ]
作者: redtek     时间: 2006-10-4 05:12
过瘾!!!给pengfei兄加6分~:)
C:\TEMP>b.bat 12.99  438.76
451.75
请按任意键继续. . .

作者: redtek     时间: 2006-10-4 05:18
两位大侠之作非常精彩~~
个人感觉要学好批处理和DOS批处理以及脚本的应用,
其实就相当于在一步一步走向编程的道路:)

或是开发人员以一种程序思维、和数据结构的理解方式来让批处理达到一个更高的水平:)

这就是为什么很多网友学了DOS批处理应用以后,
过了好多年再也提不高的原因之一:)

而有的大侠,确是每一天每一步都在不断的向上走,
技巧已经都不再重要了,应用到的数据结构可以解决很多问题:)
无论是在批处理里面还是在代码开发上,它们都是相通的:)

[ Last edited by redtek on 2006-10-4 at 05:21 ]
作者: pengfei     时间: 2006-10-4 10:15
终于解决了小数位数的局限, 可以运算各种类型的数值, 小数位数不受限制. 暂时没有解决错误输入的问题.

代码更新在4楼!
作者: namejm     时间: 2006-10-4 11:18
  发一段代码,匆忙中没来得及对数据进行查错处理和代码的优化,可以适应小数位数不一致的情况。基本思路是对数值的整数部分和小数部分分别进行计算:
@echo off
cls
set input1=
set input2=
set /p input1=请输入第一个数值:
set /p input2=请输入第二个数值:
setlocal enabledelayedexpansion
for /f "tokens=1-4 delims=." %%i in ("%input1%.%input2%") do (
    set num1=%%i
    set num2=%%j
    set num3=%%k
    set num4=%%l
    set length=0
    call :get_length %%j
    set length1=!length!
    echo !length1!
    set length=0
    call :get_length %%l
    set length2=!length!
    echo !length2!
    call :add_zero
    set /a sum1=!num1!+!num3!
    set /a sum2=!num2!+!num4!
    call :set_num
    if !sum2! geq !str! set /a sum2=!sum2!-!str! & set /a sum1=!sum1!+1
    echo !sum1!.!sum2!
)
pause
goto :eof

:get_length
for /f %%i in ("%1") do (
    set /a length+=1
    set var=%%i
    if not "!var!"=="" set var=!var:~0,-1!&& call :get_length !var!
)
goto :eof

:add_zero
set /a cha=%length1%-%length2%
set cha=%cha:-=%
if %cha% gtr 0 (
    for /l %%i in (1,1,%cha%) do set str=!str!0
    echo !str!
    if %length1% gtr %length2% (set num4=%num4%!str!) else (set num2=%num2%!str!)
)
echo %num2%   %num4%
goto :eof

:set_num
if %length1% geq %length2% (set longer=%length1%) else (set longer=%length2%)
set str=
for /l %%i in (1,1,%longer%) do set str=!str!0
set str=1%str%
echo %str%
goto :eof
[ Last edited by namejm on 2006-10-4 at 11:20 ]
作者: electronixtar     时间: 2006-10-4 20:17
还是脚本简单些 ^_^
作者: pengfei     时间: 2006-10-4 23:50
解决了小数点后第一位为0且后面出现8或9, 导致数值为无效数字的问题.

一个全新的算法, 大概的意思是, 读取小数位数不足的补零. 去.号后小数和整数一起运算, 运算完成后再根据记录的小数点位置准确地插入到相应的地方, 从而完成了浮点数值的运算.

这段代码具有更好的通用性, 时间仓促没来得及优化:
整数浮点数合并运算代码:
整数位最多可运算8位数, 小数位最多可运算8位数.
小数位整数位加起来最多可运算9位数
否则会溢出或为无效数字...

用取位循环去零法解决了最高位为零或多个零的问题, 可以测试(0.0  .23  12.  .)的数值运算.
解决了(0.0+0.0289), (0.08+1.029)之类的进制问题.
目前测试可以适应各种情况.
期待大家进行全面测试...

@echo off
set /p number=请输入运算数一:
set /p number_=请输入运算数二:
call :omit %number%
set number=%want%
call :omit %number_%
set number_=%want%
echo %number% | find "." >nul || set number=%number%.0
echo %number_% | find "." >nul || set number_=%number_%.0
if "%number:~-1%"=="." set number=%number%0
if "%number_:~-1%"=="." set number_=%number_%0
if "%number:~0,1%"=="." set number=0%number%
if "%number_:~0,1%"=="." set number_=0%number_%
setlocal enabledelayedexpansion
for %%a in (%number% %number_%) do (
    set /a num+=1
    for /f "tokens=1,2 delims=." %%i in ("%%a") do (
        if "!num!"=="1" (set one=%%i) else (set one_=%%i)
        if "!num!"=="1" (set two=%%j) else (set two_=%%j)
    )
)
call :go %two%
set num1=%wish%
call :go %two_%
set num2=%wish%
if %num1% lss %num2% (
    set note=%num2%
    set /a result=%num2%-%num1%
    call :fine !result! %two%
    set two=!incept!
) else (
    set note=%num1%
    set /a result=%num1%-%num2%
    call :fine !result! %two_%
    set two_=!incept!
)
set term=0
if %one:~0,1%==0 set one=!one:~1!
if %one_:~0,1%==0 set one_=%one_:~1%
if "%one%"=="" (
    set one=1
    set /a term+=1
)
if "%one_%"=="" (
    set one_=1
    set /a term+=1
)
set /a fruit_=%one%%two%+%one_%%two_%
set fruit_=:%fruit_%
:insert
if not "!fruit_:~-1!"==":" (
    if "!num_!"=="%note%" (
        set fruit=.!fruit!
        set /a ii=!fruit_:~1!-%term%
        set fruit_=:!ii!
    )
    set fruit=!fruit_:~-1!!fruit!
    set fruit_=!fruit_:~0,-1!
    set /a num_+=1
    goto insert
)
echo %fruit%
pause
exit

:go
set remove=%1
set wish=0
:go_
if not "!remove:~0,1!"=="~" (
    for /l %%c in (0,1,9) do (
        if "!remove:~0,1!"=="%%c" (
            set /a wish+=1
            set remove=!remove:~1!
            goto go_
        )
    )
)
goto :eof
:fine
set take=%1
set incept=%2
:fine_
if not "%take%"=="0" (
    set /a take-=1
    set incept=!incept!0
    goto fine_
)
goto :eof
:omit
set want=%1
:again
if "%want:~0,1%"=="0" (
    set want=%want:~1%
    goto again
)
goto :eof
[ Last edited by pengfei on 2006-10-6 at 03:51 ]
作者: namejm     时间: 2006-10-5 00:44
  pengfei 『第 10 楼』的代码先把浮点数用0把位数补齐,然后再把小数点去掉,对新数进行处理,然后再把小数点的位置复原,这个思路相当新颖,比我在『第 8 楼』的思路又更进了一步,优化之后,代码将会比我那段更简洁。看来,多多讨论真的很容易碰撞出智慧的火花^_^
作者: pengfei     时间: 2006-10-5 01:43
^_^ 呵呵~ namejm兄八楼代码的思路和我四楼的一样, 如果小数第一位是零且后面跟了8或9就会出错, 还是进制问题, 而10楼的代码则不会.
作者: 不得不爱     时间: 2006-10-5 04:44
我试了下,如果首位是0的数,后面有8和9都会出错!就是10楼的也一样!
作者: pengfei     时间: 2006-10-5 04:49
版主是在整数的最高位加零吧!

你试试在小数点后第一位加零, 再比较两段代码的运算结果.
作者: 不得不爱     时间: 2006-10-5 05:09
下面的是首位是0的数自动去0,小数点前没有数字自动加0,小数点末尾有0自动去0!
@echo off
if not %1*==* (set number=%1&set number_=%2&goto bj)
set /p number=请输入运算数一:
set /p number_=请输入运算数二:
:bj
echo %number% | find "." >nul || set number=%number%.0
echo %number_% | find "." >nul || set number_=%number_%.0
if %number:~0,1%==. set number=0%number%
if %number_:~0,1%==. set number_=0%number_%
if "%number:~-1%"=="." set number=%number%0
if "%number_:~-1%"=="." set number_=%number_%0
setlocal enabledelayedexpansion
for %%a in (%number% %number_%) do (
    set /a num+=1
    for /f "tokens=1,2 delims=." %%i in ("%%a") do (
        if "!num!"=="1" (set one=%%i) else (set one_=%%i)
        if "!num!"=="1" (set two=%%j) else (set two_=%%j)
    )
)
call :go %two%
set num1=%wish%
call :go %two_%
set num2=%wish%
if %num1% lss %num2% (
    set note=%num2%
    set /a result=%num2%-%num1%
    call :fine !result! %two%
    set two=!incept!
) else (
    set note=%num1%
    set /a result=%num1%-%num2%
    call :fine !result! %two_%
    set two_=!incept!
)
:1
set n1=0
if "!one:~0,1!"=="0" set one=!one:~1!&&goto 1
if %two:~0,1%==0 set two=1%two%&&set n1=1
:2
if "!one_:~0,1!"=="0" set one_=!one_:~1!&&goto 2
if %two_:~0,1%==0 set two_=1%two_%&&set/a n1+=1
set /a num2=%two%+%two_%
set/a n1=!num2:~0,-%note%!-%n1%
set num2=!num2:~-%note%!
set /a num1=%one%+%one_%+%n1%
:3
if !num2:~-1!==0 set num2=!num2:~0,-1!&&goto 3
if %num2%*==* (echo %num1%) ELSE echo %num1%.%num2%
PAUSE
goto :eof

:go
set remove=%1
set wish=0
:go_
if not "!remove:~0,1!"=="~" (
    for /l %%c in (0,1,9) do (
        if "!remove:~0,1!"=="%%c" (
            set /a wish+=1
            set remove=!remove:~1!
            goto go_
        )
    )
)
goto :eof
:fine
set take=%1
set incept=%2
:fine_
if not "%take%"=="0" (
    set /a take-=1
    set incept=!incept!0
    goto fine_
)
goto :eof
[ Last edited by qwe1234567 on 2006-10-6 at 07:40 ]
作者: pengfei     时间: 2006-10-5 05:22
10楼代码已更新, 可以去最高位的多个零. 请测试...
作者: 不得不爱     时间: 2006-10-5 05:37
你的要出错!
0.88+12.3=100.3
这个你没有试过?
作者: 不得不爱     时间: 2006-10-5 05:59
15楼代码已更新, 可以去最高位的多个零,接受.98这样的小数!请测试...
作者: 无奈何     时间: 2006-10-5 06:53
个人非常赞同这样的讨论方式,大家可以讨论一下更详尽评判和奖励办法。
        我也提交一卷,模拟了一下手工计算过程,主要是想练习一下字符的处理,编写过程颇为费劲,执行效率也不高。支持两个数字的各种复杂格式,并且数字长度不受限制只是会很慢。

  Quote:

  1. @echo off
  2. setlocal
  3. set number1=%~1
  4. set number2=%~2
  5. if "%number1%" == "" goto :EOF
  6. if "%number2%" == "" set number2=0
  7. set D1=0
  8. set D2=0
  9. set flag=0
  10. set D1=%number1:*.=%
  11. call set I1=%%number1:.%D1%=%%
  12. set D2=%number2:*.=%
  13. call set I2=%%number2:.%D2%=%%

  14. if "%D1%" == "%number1%" set D1=0
  15. if "%D2%" == "%number2%" set D2=0
  16. set D1=1%D1%
  17. set D2=1%D2%
  18. call :fill %D1% %D2% D1 D2
  19. call :sum $%D1% $%D2%
  20. if "%sum:~0,1%" GTR "2" set /a flag=1
  21. set D_sum=%sum:~1%
  22. call :sum $%I1% $%I2%
  23. set I_sum=%sum%
  24. echo %number1% + %number2% =
  25. if %D_sum% EQU 0 (
  26.         echo.    %I_sum%
  27. ) else (
  28.         echo.    %I_sum%.%D_sum%
  29. )
  30. goto :EOF

  31. :sum
  32. set sum=
  33. set temp1=%1
  34. set temp2=%2
  35. if "%flag%" == "1" set H=1
  36. set n=1
  37. :next
  38. call set x=%%temp1:~-%n%,1%%
  39. call set y=%%temp2:~-%n%,1%%
  40. if "%x%" == "$" (
  41.         if "%y%" == "$" (
  42.                 if "%H%" GTR "0" set sum=%H%%sum%
  43.                 goto :EOF
  44. ))
  45. if "%x%" == "$" set x=0
  46. if "%y%" == "$" set y=0
  47. call :sub %x% %y% %H%
  48. set sum=%ERRORLEVEL%%sum%
  49. set /a n+=1
  50. goto next

  51. :sub
  52. set H=0
  53. if "%1" == "" exit /b 0
  54. if "%2" == "" exit /b %1
  55. if "%3" == "" call :sub %1 %2 0 &goto :EOF
  56. set /a s=%1 + %2 + %3
  57. set H=%s:~0,-1%
  58. set L=%s:~-1%
  59. exit /b %L%
  60. goto :EOF

  61. :fill
  62. setlocal
  63. set n=-1
  64. set temp1=%1
  65. set temp2=%2
  66. :loop
  67. set /a n+=1
  68. call set x=%%temp1:~%n%,1%%
  69. call set y=%%temp2:~%n%,1%%
  70. if "%x%" == "" (
  71.         if "%y%" == "" (
  72.                 endlocal &set %3=%temp1% &set %4=%temp2%
  73.                 goto :EOF
  74. ))
  75. if "%x%" == "" set temp1=%temp1%0
  76. if "%y%" == "" set temp2=%temp2%0
  77. goto :loop
  78. goto :EOF
        无奈何发表于    2006-10-04  18:56

测试代码:
call sum %RANDOM%
call sum %RANDOM% %RANDOM%
call sum .%RANDOM% %RANDOM%
call sum %RANDOM% .%RANDOM%
call sum %RANDOM%.%RANDOM% %RANDOM%
call sum %RANDOM% %RANDOM%.%RANDOM%
call sum %RANDOM%.%RANDOM% %RANDOM%.%RANDOM%
call sum %RANDOM%%RANDOM%%RANDOM%%RANDOM%%RANDOM% %RANDOM%%RANDOM%%RANDOM%%RANDOM%%RANDOM%%RANDOM%%RANDOM%
pause
[ Last edited by 无奈何 on 2006-10-5 at 07:01 ]
作者: redtek     时间: 2006-10-5 07:37
这个产生随机数的测试计算方式非常有意思啊~~~~~:)
作者: redtek     时间: 2006-10-5 07:45


  Quote:
Originally posted by pengfei at 2006-10-4 23:50:
解决了小数点后第一位为0且后面出现8或9, 导致数值为无效数字的问题.

一个全新的算法, 大概的意思是, 读取小数位数不足的补零. 去.号后小数和整 ...

(两个要计算的浮点数)
1932.00010002(小数位长度8)
    19.02310

(去小数点儿,以最长小数位对准,位数不足被补0)
193200010002
   1902310000
---------------------------
相加之和:195102320002

1951.02320002
(以合并前小数点最长的位数为基数,向左移小数点,完成浮点计算)

(另一种)
(或n个浮点的整数位相计算,n个浮点的小数位相计算,最长进位)
(浮点数左边消0消干净)

和我思考的方式一样~:)
不足补0,然后浮点数就当做一个整数与另一个当做整数的浮点运算(去点),
最后再小数点向左移位:)

激动~:)
除了激动之外就是有一点无柰,看来真正想精通批处理的网友是极少数,
对好玩的算法和象写代码一样的批处理喜欢的网友相比极少,
多数网友最喜欢用的时候想到了批处理,用不到的时候可有可无……

[ Last edited by redtek on 2006-10-5 at 08:01 ]
作者: pengfei     时间: 2006-10-5 08:37
呵呵~ qwe1234567版主真是有心, 测试也这么全面.

代码已更新在10楼! 可以去最高位的多个零. 前面各位提出的缺陷都已解决. 目前测试一切正常, 期待高手们找出更多的缺陷来. 交流才能进步... ^_^
作者: pengfei     时间: 2006-10-5 08:50
刚才测试了15楼的代码, 还是有缺陷比如(00.85   12.871)  (00.42  13.89)等.

版主说的去最高位多个零好像不行, 另外整数最前出现两个或以上的零运算会出错.
作者: namejm     时间: 2006-10-5 10:08    标题: 关于两种浮点数计算方法优劣的一点比较

  到目前为止,各位已经找到了CMD下计算浮点数的两种方法:

  方法一:浮点数的整数部分和小数部分分别计算。实现的过程是:整数部分直接相加即可;小数部分稍微有点麻烦:如果小数部分位数不一致,则要以位数最多的那个数为基准,在另外一个数的小数部分补足0,然后再对小数部分作整数的加法;如果相加的结果位数超过了最长的位数,则要向整数部分进1,小数部分的最高位要相应地减1;

  方法二:把整数部分和小数部分重组成一个新数,再对新数进行加法操作,最后把小数点插入原来的位置;

  两种方法各自的优点和缺点:

  方法一:优点:能处理的浮点数的范围很大,只要相加的结果在 (2^32-1.2^32-1) 和 -(2^32-1.2^32-1)之间,都能处理;缺点:大都出现在小数部分,如:若小数部分最高位为08或09都可能出错,要对这两种情况另作处理;小数部分相加结果的位数长度如果超过最长的位数,则要对整数部分做加1、对小数最高位作减1处理;如果扩充到三个或三个以上的浮点数进行加法操作,则进位的问题将更加复杂;

  方法二:优点:不用另行处理08和09的情况,不用考虑进位的问题(看了楼下pengfei的分析,发现这个地方的描述有点问题,具体情况请参阅楼下的描述);缺点:能处理的浮点数范围比较小,相加结果去掉小数点之后新数值的范围在 (2^32-1.2^32-1) 和 -(2^32-1.2^32-1)之间才能成功。

  以上是我的一点粗浅认识,有的地方可能不是很正确,欢迎大家一起探讨。

[ Last edited by namejm on 2006-10-5 at 10:45 ]
作者: pengfei     时间: 2006-10-5 10:14
哈哈~ 又解决一个难题.

如10楼的代码在此之前运算(0.0+0.48), 这里根据代码的运算原理, 最终运算为(000+048)显然进制错误. 这里我采用去整数零位, 只进行小数位运算.

当解决整数个位为零的问题时, 另一个问题又出现了(0.5+0.082), 最终运算为(500+082), 呵呵~ 整数的零刚去掉, 小数位的零又出现了, 还是无效数字. 头晕...

先前解决上面的问题, 采取整数个位都赋1. 虽然可以解决个位都为零的问题, 但如果其中一个运算数个位不为零, 另一个不为零. 这种方法就行不通了.

现在采用其中一个运算数个位为零就赋1值. 两个都为零两个都赋1. 然后计数变量相应的加1. 最后处理运算结果时, 当处理到个位时相应的减去计数值. 这样就解决了这个进制问题!

目前测试暂时没有发现问题! 代码已更新在10楼~~~!

[ Last edited by pengfei on 2006-10-5 at 22:31 ]
作者: pengfei     时间: 2006-10-5 10:40
『第 19 楼』 无奈何版主的代码好强~~~!
作者: 无奈何     时间: 2006-10-5 10:42
计算浮点位或整数位的前置零的简便方法是:在数字最前位补 1 ,计算后判断最前位是否是 2 ,是的话去掉最前位,不是的话也去掉最前位并在最前位补 1 。
浮点位需补零对齐。

[ Last edited by 无奈何 on 2006-10-5 at 10:45 ]
作者: pengfei     时间: 2006-10-5 10:44
呵呵~ 我正是用这种方法来实现的.
作者: 不得不爱     时间: 2006-10-5 23:58
15楼代码已更新, 可以去最高位的多个零,接受.98这样的小数!请测试...
作者: pengfei     时间: 2006-10-6 00:12
关于整数浮点数分段运算代码:

代码更新在4楼~~~! 解决了小数位第一位为零可能出现进制错误的问题. 目前测试可以适应各种不同情况.

下面是对4楼和10楼代码的运算范围的比较:
整数浮点数分段运算代码: (代码请见4楼)
整数位最多可运算9位数, 小数位最多可运算8位数.
小数位整数位加起来最多可运算17位数.
否则会溢出或为无效数字...

整数浮点数合并运算代码: (代码请见10楼)
整数位最多可运算8位数, 小数位最多可运算8位数.
小数位整数位加起来最多可运算9位数
否则会溢出或为无效数字...
欢迎大家测试...

[ Last edited by pengfei on 2006-10-6 at 03:50 ]
作者: 不得不爱     时间: 2006-10-6 00:38
15楼代码已更新为整数浮点数分段运算
欢迎大家测试...
作者: 不得不爱     时间: 2006-10-6 01:11
10楼代码错误!
请输入运算数一:132165.134646454
请输入运算数二:132654.6546546
-2
132165.134646454+132654.6546546=-2?
作者: pengfei     时间: 2006-10-6 03:38
10楼已经说明, 小数位最多可运算8位数. 而你的小数部分为9位, 溢出了...

发现15楼的代码有几点缺陷; 运算错误, 多加了1. 零的问题上没有考虑完全(111+111=223), (0.23+1.08=2.31)...  

版主还需要改进代码, 具体10楼的代码和4楼的代码都用最前位添1的办法解决了(这也是为什么10楼和4楼的代码小数部分只能运算8位的原因了).
关于10楼(整数浮点数合并运算)代码的注意事项:

整数位最多可运算8位数, 小数位最多可运算8位数.
小数位整数位加起来最多可运算9位数
否则会溢出或为无效数字...
[ Last edited by pengfei on 2006-10-6 at 04:05 ]
作者: pengfei     时间: 2006-10-6 03:41
另外4楼的代码经过改进已经可以通用了, 甚至比10楼的代码更具优越性.

具体表现在它的运算范围更大, 小数整数最多可以运算17位. 代码更简洁, 容错性更好!

刚写出来, 可能还有些问题还没有考虑进去. 期待大家进行全面测试...
作者: 不得不爱     时间: 2006-10-6 07:43
我刚才检查了下,原来是把set/a n1+=1打成了set n1+=1,所以出错。
15楼已经更新!小数最多可以9位,整数最多可以运算9位,支持A 136.987 236这种输入和输入A后按照提示输入!
欢迎大家测试...

[ Last edited by qwe1234567 on 2006-10-7 at 03:45 ]
作者: 不得不爱     时间: 2006-10-6 07:50
4楼上面的代码有错误,整数前有0就出错,小数后位对不齐!
a 008.64 36.6
无效数字。数字常数只能是十进制(17),十六位进制(0x11)或
八进制(021)。
.70
请按任意键继续 . . .
a 8.64 36.6
44.70

[ Last edited by qwe1234567 on 2006-10-6 at 07:54 ]
作者: pengfei     时间: 2006-10-6 09:52
版主这种a 008.64属于错误输入的范筹吧, 这个我是没考虑过, 还是测试浮点运算可能出现的各种情况吧! 36楼测试的错误我并没有发现...

版主说的前面有0就出错, 肯怕不会吧, 取位循环去零法可以去最高位所有的零.

而小数后位对不齐, 这是格式输出的问题, 也没有考虑, 代码只作为测试运算结果的对与否. 如果坚持要格式输出的话也可以考虑加入相应代码.

欢迎大家测试4楼和10楼代码的运算缺陷...

[ Last edited by pengfei on 2006-10-6 at 10:16 ]
作者: 不得不爱     时间: 2006-10-6 19:29
就是我把4楼上面的代码(输入是%1和%2的那个文件)写入A.BAT文件里,然后在CMD里输入:
a 008.64 36.6
无效数字。数字常数只能是十进制(17),十六位进制(0x11)或
八进制(021)。
.70
请按任意键继续 . . .
a 8.64 36.6
44.70
作者: pengfei     时间: 2006-10-6 19:42
呵呵~  我那段代码只限于在批处理中运算, 不能接受变量%1, %2的输入. 版主应该一看就知道.

恭喜你的代码已经加入取位循环去零法和小数位前添1运算代码, 解决了这一系列问题. 还增加了在CMD下使用的代码^_^

目前第4楼, 第10楼, 以及qwe1234567版主的代码测试一切正常...
作者: 不得不爱     时间: 2006-10-6 23:34
那请问4楼上的里的%1和%2是接受哪儿的变量?(下面的代码是你4楼上面的,请看!)
@echo off
setlocal enabledelayedexpansion
for %%a in (%1,%2) do (
    set /a num+=1
    for /f "tokens=1,2 delims=." %%i in ("%%a") do (
        if "!num!"=="1" (set one=%%i) else (set one_=%%i)
        if "!num!"=="1" (set two=%%j) else (set two_=%%j)
    )
)
set /a integer=%one%+%one_%
set /a decimal=%two%+%two_%
if %decimal:~0,1% lss %two:~0,1% (
    set /a integer=%integer%+1
    set /a decimal=%decimal:~1%
) else (
    if %decimal:~0,1% lss %two_:~0,1% (
        set /a integer=%integer%+1
        set /a decimal=%decimal:~1%
    )
)
echo %integer%.%decimal%
pause
里的%1和%2是接受哪儿的变量?
作者: pengfei     时间: 2006-10-6 23:35
这一段脚本是最初的, 很多问题都没解决, 4楼下面还有一段呢?
作者: 不得不爱     时间: 2006-10-7 03:08
4楼下面那段是没有问题!
作者: 不得不爱     时间: 2006-10-8 00:13
新思路计算方法:
计算前小数位首位自动去0、尾数自动去0,整数首位自动去0,最大的得数是:2147483647.2147483647(小数位最大得数是.2147483647、整数最大得数是.2147483647)
如果加数的小数位首位都有N个以上的0,小数位的位数可以多到N+9个以上!
欢迎大家测试!
321.00000000065496546+13.000000000046541346=334.000000000701506806
321.1105496546+13.1041541346=334.2147037892
@echo off
if not %1*==* (set number=%1&set number_=%2&goto bj)
set /p number=请输入运算数一:
set /p number_=请输入运算数二:
:bj
echo %number% | find "." >nul || set number=%number%.0
echo %number_% | find "." >nul || set number_=%number_%.0
if %number:~0,1%==. set number=0%number%
if %number_:~0,1%==. set number_=0%number_%
if "%number:~-1%"=="." set number=%number%0
if "%number_:~-1%"=="." set number_=%number_%0
setlocal enabledelayedexpansion
for /f "tokens=1-4 delims=." %%a in ("%number%.%number_%") do (
set one=%%a
set two=%%b
set one_=%%c
set two_=%%d
)
call :go %two%
set two=%ls%
set num1=%wish%
call :go %two_%
set two_=%ls%
set num2=%wish%
if %num1% lss %num2% (
set note=%num2%
set /a result=%num2%-%num1%
call :fine !result! %two%
set two=!incept!
) else (
set note=%num1%
set /a result=%num1%-%num2%
call :fine !result! %two_%
set two_=!incept!
)
:1
if "!one:~0,1!"=="0" set one=%one:~1%&&goto 1
:11
if "!two:~0,1!"=="0" set two=%two:~1%&&goto 11
if %two%*==* set two=0
:2
if "!one_:~0,1!"=="0" set one_=!one_:~1!&&goto 2
:22
if "!two_:~0,1!"=="0" set two_=!two_:~1!&&goto 22
if %two_%*==* set two_=0
set/a num2=%two%+%two_%
set/a n1=0!num2:~0,-%note%!
if %num2%==0 set num2=&&goto go3
set num2=!num2:~-%note%!
set ls=%num2%
:go1
if not %ls%*==* (
set ls=!ls:~1!
set/a go+=1
goto go1
)
:go2
if not %go%*==%note%* (
set/a go+=1
set num2=0%num2%
goto go2
)
:go3
set /a num1=%one%+%one_%+%n1%
:3
if !num2:~-1!==0 set num2=!num2:~0,-1!&&goto 3
if %num2%*==* (echo %number%+%number_%=%num1%) ELSE echo %number%+%number_%=%num1%.%num2%
PAUSE
goto :eof

:go
set remove=%1
set wish=0
:q0
if %remove:~-1%*==0* (
set remove=!remove:~0,-1!
goto q0
)
set ls=%remove%
:go_
if not %remove%*==* (
set /a wish+=1
set remove=!remove:~1!
goto go_
)
goto :eof
:fine
set take=%1
set incept=%2
:fine_
if not "%take%"=="0" (
set/a take-=1
set incept=!incept!0
goto fine_
)
goto :eof
[ Last edited by qwe1234567 on 2006-10-8 at 05:20 ]
作者: pengfei     时间: 2006-10-8 04:47
看了一下版主的代码有两点改进:
1.  在读取两个运算数的整数小数部分时, 你放到一起的方法提取. 思路不错^_^
2.  小数部分首位为零就去零运算. (这里小数部分前置零是不影响运算的, 这点和整数运算一样)

这段代码虽然发现小数运算暂时没有出错, 但却不能运算整数了(原因在于去小数最前位零, 如果只有一个零就没有运算数了. 甚至以后的几句代码都会出错).这里个问题倒可以解决.

以前觉得小数前全部添1简单省事, 但却只能运算8位. 呵呵~ 还是觉得更大的运算范围更重要, 代码正在更新中...
作者: 不得不爱     时间: 2006-10-8 05:22
去小数最前位零, 如果只有一个零就没有运算数了. 甚至以后的几句代码都会出错的问题已经解决。更新在43楼。
欢迎大家测试!
作者: pengfei     时间: 2006-10-9 05:10
qwe1234567版主43楼去小数位前置零再运算的方案很不错. 在小数进位时很好地玩了一把字符截取, 玩得漂亮. ^_^

小数整数都可以运算9位数的代码更新在4楼第一段.

加入了判断错误输入的功能. 如:
1.  如果输入的运算数中存在除阿拉伯数以外的字符, 将提示你重新输入.
2.  若小数和整数位数超过脚本运算范围, 也会让你重新输入.

该脚本为只要你能看到最终的运算结果, 应该都是正确的!

期待大家把没有考虑到的问题测试出来...
作者: pengfei     时间: 2006-10-9 20:24
终于解决浮点运算对字符位数的限制, 理论上可以运算N位的数值范围.

算法:
1.  把输入的两个运算值, 分别以.号做为基准, 向两端补零对齐(在这之前已经去掉了无用的零), 小数和整数部分分别赋给不同变量.
2.  先运算小数部分, 将第1个数的最后一位和第2个数的最后一位做加法运算. 再将运算结果的最后一位赋给结果变量1.,如果运算结果存在两位数, 运算次低位时自动加1. 如此循环, 直到把小数的所有位数运算完成. 得到了小数部分的运算数.
2.  整数部分的运算和小数的一样. 得到结果变量2.
3.  结果变量1, 结果变量2. 将他们中间加.号就得到了准确的运算结果...

欢迎大家测试...
@echo off
if not %1*==* set num1=%1 & set num2=%2 & goto jmp
:input
cls
set num1=
set /p num1=input primary number:
set num2=
set /p num2=input number two number:
:jmp
set numx=%num1%
set numy=%num2%
echo %num1% | find "." >nul || set num1=%num1%.0
echo %num2% | find "." >nul || set num2=%num2%.0
if "%num1:~-1%"=="." set num1=%num1%0
if "%num2:~-1%"=="." set num2=%num2%0
if "%num1:~0,1%"=="." set num1=0%num1%
if "%num2:~0,1%"=="." set num2=0%num2%
set num=0
setlocal enabledelayedexpansion
for %%a in (%num1% %num2%) do (
    set /a num+=1
    for /f "tokens=1,2 delims=." %%i in ("%%a") do (
        if "!num!"=="1" (set one=%%i) else (set one_=%%i)
        if "!num!"=="1" (set two=%%j) else (set two_=%%j)
    )
)
call :omit %one%
set one=%want%
call :omit %one_%
set one_=%want%
call :raze %two%
set two=%want_%
call :raze %two_%
set two_=%want_%
if "%one%"=="" set one=0
if "%one_%"=="" set one_=0
call :go %one%
set countx=%wish%
call :go %one_%
set countx_=%wish%
if "%two%"=="" set two=0
if "%two_%"=="" set two_=0
call :go %two%
set county=%wish%
call :go %two_%
set county_=%wish%
set after=
set front=0
if %countx% lss %countx_% (
    set /a result=%countx_%-%countx%
    call :fine !result! %one%
    set one=!incept!
) else (
    set /a result=%countx%-%countx_%
    call :fine !result! %one_%
    set one_=!incept!
)
set after=0
set front=
if %county% lss %county_% (
    set /a result=%county_%-%county%
    call :fine !result! %two%
    set two=!incept!
) else (
    set /a result=%county%-%county_%
    call :fine !result! %two_%
    set two_=!incept!
)
set outcome=0
call :scale @%two% @%two_%
set decimal=%numeral:~0,-1%
call :scale @%one% @%one_%
if "%note%"=="0" (
    set integer=%numeral:~0,-1%
) else (
    set integer=1%numeral:~0,-1%
)
call :raze %decimal%
set decimal=%want_%
if "%decimal%"=="" (set dot=) else (set dot=.)
if "%numx:~0,1%"=="." set numx=0%numx%
if "%numy:~0,1%"=="." set numy=0%numy%
if "%numx:~-1%"=="." set numx=%numx:~0,-1%
if "%numy:~-1%"=="." set numy=%numy:~0,-1%
cls
echo ===============
echo 运算结果^^!
echo ===============
echo.
echo.
echo %numx%+%numy%=%integer%%dot%%decimal%
pause >nul
goto :eof

:scale
set value=%1
set value_=%2
set numeral=
:repeat
set numeral=%outcome:~-1%%numeral%
set note=0%outcome:~0,-1%
if not "%value:~-1%"=="@" (
    set xx=!value:~-1!
    set value=!value:~0,-1!
)
if not "%value_:~-1%"=="@" (
    set yy=!value_:~-1!
    set value_=!value_:~0,-1!
    call :operation !xx! !yy!
)
goto :eof
:operation
set refer=%1
set refer_=%2
set /a outcome=%refer%+%refer_%+%note%
goto repeat
:go
set remove=%1@
set wish=0
:go_
if not "!remove:~0,1!"=="@" (
    set fault=1
    for /l %%c in (0,1,9) do (
        if "!remove:~0,1!"=="%%c" (
            set /a wish+=1
            set remove=!remove:~1!
            set fault=2
            goto go_
        )
    )
    if "!fault!"=="1" goto error
    goto go_
)
goto :eof
:fine
set take=%1
set incept=%2
:fine_
if not "%take%"=="0" (
    set /a take-=1
    set incept=%front%!incept!%after%
    goto fine_
)
goto :eof
:omit
set want=%1
:omit_
if "%want:~0,1%"=="0" (
    set want=%want:~1%
    goto omit_
)
goto :eof
:raze
set want_=%1
:raze_
if "!want_:~-1!"=="0" (
    set want_=!want_:~0,-1!
    goto raze_
)
goto :eof
:error
cls
echo =====================================
echo.
echo 你的输入了非法字符^^!
echo.
echo =====================================
echo.
echo.
echo 按任意键重新输入...
pause >nul
goto input
[ Last edited by pengfei on 2006-10-11 at 09:07 ]
附件 1: 实数加法运算脚本.rar (2006-10-11 09:11, 1.23 K, 下载附件所需积分 1点 ,下载次数: 13)

作者: NaturalJ0     时间: 2006-10-9 20:57
看了下你的描述,代码还没仔细看,要是说错了别见怪。 = =b
我觉得整数部分和小数部分可以不分开。开头你已经把数位都对齐了,应该补的零也补好了。小数部分有几位也是清楚的,直接去掉小数点,当一个整数处理,处理好后再补上小数点,最后把末尾多余的零去掉。
作者: pengfei     时间: 2006-10-9 21:44
RE:NaturlJ0

我把小数和整数分开是考虑到格式输出的问题. 如果小数部分为零就不输出0和点号.
作者: namejm     时间: 2006-10-10 09:12
  我也来一段代码,按位做加法操作的,理论上可以对N位的数值进行处理。稍显遗憾的是,对输入的检测不甚严格。
@echo off
:: 分别把两个数的整数和小数部分提取出来
:: 整数部分在高位用0补齐,小数部分在低位用0填充,使得两个数的数位各自对齐
:: 从小数的最低位开始,按位计算两个数的和,超过9就向次高位进1,只到整数的最高位为止
:: 例如:要计算 4567.5+5.6789,则处理后的数字为4567.5000+0005.6789,然后按位做加法操作

:main
cls
set num1=
set num2=
set /p num1=请输入第一个数:
call :input_check "%num1%" num1
set /p num2=请输入第二个数:
call :input_check "%num2%" num2

setlocal enabledelayedexpansion
for /f "tokens=1-4 delims=." %%i in ("%num1%.%num2%") do (
    set int1=%%i
    set int2=%%k
    set dec1=%%j
    set dec2=%%l
    call :get_length int1 %%i
    call :get_length int2 %%k
    call :get_length dec1 %%j
    call :get_length dec2 %%l
    call :add_zero
    call :sum
)
pause
goto :eof

:input_check
rem =========== 检测输入是否正确 ===========
echo %1|findstr "\.">nul||set %~2=%~1.0
for /f "tokens=1* delims=." %%i in (%1) do (
    echo %%i%%j|findstr "^[0-9]*$">nul || goto main
)
goto :eof   

:get_length
rem =========== 计算各部分数字的长度 ===========
set count=0
:intercept
set /a count+=1
for /f %%i in ("%2") do (
    set var=%%i
    if not "!var:~%count%,1!"=="" goto intercept
    set %1_length=!count!
)
goto :eof

:add_zero
rem =========== 分别在整数部分和小数部分添加0字符串 ===========
:: 在数位不够的整数部分添0补齐
set /a int_length_diff=%int1_length%-%int2_length%
set int_length_diff=%int_length_diff:-=%
call :creat_zero int_zero %int_length_diff%
if %int1_length% gtr %int2_length% (
    set int2=%int_zero%%int2%
    set int_length_max=%int1_length%
    ) else (
    set int1=%int_zero%%int1%
    set int_length_max=%int2_length%
)
:: 在数位不够的小数部分添0补齐
set /a dec_length_diff=%dec1_length%-%dec2_length%
set dec_length_diff=%dec_length_diff:-=%
call :creat_zero dec_zero %dec_length_diff%
if %dec1_length% gtr %dec2_length% (
    set dec2=%dec2%%dec_zero%
    set dec_length_max=%dec1_length%
    ) else (
    set dec1=%dec1%%dec_zero%
    set dec_length_max=%dec2_length%
)
goto :eof

:creat_zero
rem =========== 根据数字字符串长度的差异,生成相应长度的0字符串 ===========
set zero=
for /l %%i in (1,1,%2) do set zero=!zero!0
set %1=%zero%
goto :eof

:sum
rem =========== 对小数部分和整数部分分别求和 ===========
:: 计算小数部分
set dec_sum=
set tmp_sum=
set switch=0
for /l %%i in (1,1,%dec_length_max%) do (
    set dec1_char=!dec1:~-%%i,1!
    set dec2_char=!dec2:~-%%i,1!
    set /a tmp_sum=!dec1_char!+!dec2_char!+!switch!
    if !tmp_sum! gtr 9 (
        set /a tmp_sum=!tmp_sum!-10
        set switch=1
        ) else (
        set switch=0
    )
    set dec_sum=!tmp_sum!!dec_sum!
)

:: 计算整数部分
set int_sum=
set tmp_sum=
for /l %%i in (1,1,%int_length_max%) do (
    set int1_char=!int1:~-%%i,1!
    set int2_char=!int2:~-%%i,1!
    set /a tmp_sum=!int1_char!+!int2_char!+!switch!
    if !tmp_sum! gtr 9 (
        set /a tmp_sum=!tmp_sum!-10
        set switch=1
        ) else (
        set switch=0
    )
    set int_sum=!tmp_sum!!int_sum!
)
if %switch% equ 1 (
    echo  %num1%+%num2%=1%int_sum%.%dec_sum%
    ) else (
    echo  %num1%+%num2%=%int_sum%.%dec_sum%
)
goto :eof
[ Last edited by namejm on 2006-10-10 at 09:32 ]
作者: pengfei     时间: 2006-10-10 09:48
namejm兄也得不错吗. ^_^

47楼代码修正了最后进位时的毛病, 多谢namejm兄提醒.

欢迎大家测试...
作者: redtek     时间: 2006-10-10 20:43
建议将代码传入国际著名的DOS批处理交流网站(我不知道是哪个站点),
代码上标注上 www.cn-dos.net 以及 China 中国字样~:)

将来把创新、改进、实用的东东同时也放到全世界著名的批处理交流网站上(英文站点),让这些智慧的创造烙上中国的印章~:)
作者: pengfei     时间: 2006-10-10 22:50
其实批处理和其他高级语言一样, 算法是灵魂, 创新是动力. 而结构化程序设计的思想是我们必须坚持的理念.

三种基本结构(顺序结构, 选择结构, 循环结构)是可以解决任何复杂问题的.

当你更深地认识了这种结构化的设计思路, 写代码也就非常容易了.
作者: electronixtar     时间: 2006-10-11 01:21
五体投地~~
作者: namejm     时间: 2006-10-11 01:26
  到目前为止,各位的代码都只能处理非负的浮点数,下一步该考虑一下怎么处理纯负数、正负数混合的情况,以使得代码能真正处理所有的浮点数。
作者: pengfei     时间: 2006-10-11 01:33
经过测试, 我47楼的代码和namejm版主的代码已经没有任何问题.

这个问题得到完美的解决, 不但能够处理浮点运算, 还解决了批处理运算位数的限制(发现很多计算器都有位数限制,  windows自带的计算器只能运算31位. 看来我们的脚本在这个方面可以发挥他的特长了, 哈哈~~~!)

正想把这个无限制加减法运算的代码合并, 代码正在编写ing...  将放到我那个实数运算脚本的帖子中去!
作者: vkill     时间: 2006-10-11 02:09
佩服,佩服~~
作者: 不得不爱     时间: 2006-10-11 02:46
终于解决浮点运算对字符位数的限制, 理论上可以运算N位的数值范围.
分别把两个数的整数和小数部分提取出来
小数部分在低位用0填充,使得两个数的数位各自对齐
从小数的最低位开始,按每位计算1次两个数的和,超过9就向次高位进1,直到整数的最高位为止
(47楼计算带2个小数点的小数出现错误,
32165.464.1654 +1321.654.31654 =33487.1118
50楼计算首位是小数点也出现错误,
请输入第一个数:.31654
请输入第二个数:1.31654
找不到操作数。
命令语法不正确。)
在本代码了都没有哪两个问题。47楼和50楼的代码还需要改进。
@echo off
setlocal enabledelayedexpansion
if not %1*==* (set num1=%1&if not %2*==* (set num2=%2&goto jmp) ELSE goto err)
ECHO 1
:input
set/p num1=请输入第一个小数:
set/p num2=请输入第二个小数:
:jmp
if %num1%*==* goto err
if %num2%*==* goto err
set err=0
if %num1:~0,1%==. set num1=0%num1%
call :qc "%num1%" num1
if %num2:~0,1%==. set num2=0%num2%
call :qc "%num2%" num2
if %err%==1 goto err
for /f "tokens=1* delims=." %%a in ("%num1%") do (set o1=%%a
set t1=%%b)
for /f "tokens=1* delims=." %%a in ("%num2%") do (set o2=%%a
set t2=%%b)
call :qs0 %o1%
set o1=%sw%
call :qs0 %o2%
set o2=%sw%
call :qw0 %t1%
set t1=%sw%
call :qw0 %t2%
set t2=%sw%
call :js %t1%
set s1=%sw%
call :js %t2%
set s2=%sw%
If %s1% Geq %s2% (set/a s3=%s1%-%s2%
call :j0 !s3! %t2%
set tmp1=%o1%%t1%
set tmp2=%o2%!sw!
) ELSE (set/a s3=%s2%-%s1%
call :j0 !s3! %t1%
set tmp1=%o1%!sw!
set tmp2=%o2%%t2%
set s1=%s2%)
set jg1=0
set jg=
ECHO %tmp1% %tmp2%
:js2
set/a jg0=%tmp1:~-1%+%tmp2:~-1%+%jg1%
set jg1=0%jg0:~0,-1%
set jg=%jg0:~-1%%jg%
set tmp1=%tmp1:~0,-1%
set tmp2=%tmp2:~0,-1%
if %tmp1%*==* (if %tmp2%*==* (if %jg1%==01 (set jg=1%jg%&goto xs) ELSE goto xs) ELSE set tmp1=0&goto js2)
if %tmp2%*==* (if %jg1%==01 (set tmp2=0&goto js2) ELSE (set jg=%tmp1%%jg%&goto xs))
goto js2
:xs
call :qw0 !jg:~-%s1%!
set jg=!jg:~0,-%s1%!.%sw%
if %jg:~-1%==0 set jg=%jg:~0,-2%
:cls
echo 计算结果是:
if not %t1%==0 set o1=%o1%.%t1%
if not %t2%==0 set o2=%o2%.%t2%
echo %o1%+%o2%=%jg%
pause
goto :eof

:qs0
set sw=%1
:qs1
if %sw%==0 goto :eof
if %sw:~0,1%==0 set sw=!sw:~1!&goto qs1
goto :eof
:qw0
set sw=%1
:qw1
if %sw%==0 goto :eof
if %sw:~-1%==0 set sw=!sw:~0,-1!&goto qw1
goto :eof
:js
set sw=0
set sw1=%1
if %sw1%==0 set sw=1&goto :eof
:js1
if not %sw1%*==* set sw1=%sw1:~1%&set/a sw+=1&goto js1
goto :eof
:qc
echo %1|findstr "\.">nul||set %~2=%~1.0
for /f "tokens=1* delims=." %%i in (%1) do echo %%i%%j|findstr "^[0-9]*$">nul||set err=1
goto :eof
:j0
set sw1=%1
set sw=%2
if %sw1%==0 goto :eof
for /l %%c in (1,1,%sw1%) do set sw=!sw!0
goto :eof
:err
echo 你输入了非法字符^!
echo 请重新输入...
goto input
[ Last edited by qwe1234567 on 2006-10-11 at 09:33 ]
附件 1: 实数计算脚本.rar (2006-10-11 09:33, 834 bytes, 下载附件所需积分 1点 ,下载次数: 9)

作者: 不得不爱     时间: 2006-10-11 02:47


  Quote:
Originally posted by pengfei at 2006-10-11 01:33:
经过测试, 我47楼的代码和namejm版主的代码已经没有任何问题.

这个问题得到完美的解决, 不但能够处理浮点运算, 还解决了批处理运算位数的限制(发砮..

两位的代码都有点问题!看下我的!
作者: vkill     时间: 2006-10-11 02:52


  Quote:
Originally posted by qwe1234567 at 2006-10-11 02:46:
终于解决浮点运算对字符位数的限制, 理论上可以运算N位的数值范围.
分别把两个数的整数和小数部分提取出来
小数部分在低位用0填充,使得两个数 ...

计算结果是:
0.9999999999999999999999999999999999999999999999999999999999999+0.77777777777777
7=177.7777769777777769999999999999999999999999999999999999999999999
请按任意键继续. . .
???
作者: 不得不爱     时间: 2006-10-11 04:17
原来是一次算9位引起的,已经修改位一次算1位,请检查!
47楼的代码计算结果是:
0.9999999999999999999999999999999999999999999999999999999999999 +0.7777777777777
7 =1.17777777777777699999999999999999999999999999999999999999999999
作者: pengfei     时间: 2006-10-11 08:24
关于qwe1234567版主提出的几点问题, 都属于错误输入的范筹, 而脚本的运算是绝对没有任何问题的...

由于时间的关系对错误输入的检测稍候再改进~~~!
作者: 不得不爱     时间: 2006-10-11 08:56
0.9999999999999999999999999999999999999999999999999999999999999 和0.77777777777777那个是错误输入的?
作者: 不得不爱     时间: 2006-10-11 08:58
0.9+0.7=1.16
0.99+0.77=1.176
0.99+0.7=1.169
0.999 +0.77 =1.1769这是不是错误输入?

[ Last edited by qwe1234567 on 2006-10-11 at 09:03 ]
作者: pengfei     时间: 2006-10-11 09:13
sorry 我指的是输入两个小数点的情况.

由于时间关系没来得及测试, 你说的问题已经解决, 代码更新在47楼...
作者: 不得不爱     时间: 2006-10-11 09:37
看了下,你的代码有3.53K压缩后有1.23K我的代码有2.11K压缩后有834bytes
作者: pengfei     时间: 2006-10-11 09:46
嗯,你代码中的变量名都用简单的j0, jq1等, 并且复合语句都写在一行.

而我写的变量名都用一些英文单词, 并且所有的复合语句每一句命令都另起一行再在前面空两格(已经习惯了, 代码更好看些). 不太喜欢用管道命令把命令拼接起来.  这样产生大量的空格, 英语单词虽然使用得不好, 但也是为了见名知意.

[ Last edited by pengfei on 2006-10-11 at 09:57 ]
作者: pengfei     时间: 2006-10-12 08:30
功能更加强大的加减法运算脚本已经完成, 请测试...

http://www.cn-dos.net/forum/viewthread.php?tid=23611&fpage=1
作者: 不得不爱     时间: 2006-10-12 21:35
我也来一段,特点是体积小,计算快,可以计算任意位小数! 请测试...
http://www.cn-dos.net/forum/viewthread.php?tid=23611
作者: vkill     时间: 2006-10-13 01:38
昨天想了一个晚上想到的也就是补位等,下回去代码好好看看
作者: redtek     时间: 2006-10-13 02:42
如果使用中国珠算的进位原理,估计算乘、除的任意位数都没有问题了~:)
作者: namejm     时间: 2006-10-13 06:49
  因为CMD功能有限,做除法运算的时候,对整数除法结果的小数部分直接做丢弃处理,并且不能处理小数除法,所以,用CMD来做除法运算应该慎之又慎。

  按位做乘法运算的方法是行得通的,实际上加法运算就已经包含了乘法运算的部分功能,各位有兴趣的话,可以在加法代码的基础上扩充一下。
作者: vkill     时间: 2006-10-13 08:02


  Quote:
Originally posted by namejm at 2006-10-13 06:49:
  因为CMD功能有限,做除法运算的时候,对整数除法结果的小数部分直接做丢弃处理,并且不能处理小数除法,所以,用CMD来做除法运算应该慎之叠...

原理上是可以行的通的,这几天家停电,等几天发个1000个以内数的加和10个数以内的乘,呵呵,基本的东西已经构思好了
作者: pengfei     时间: 2006-10-13 08:16
实现乘法运算完全可行, 前几天我已经完成了最简单的乘法运算脚本, 但如果运算位数大时就代码就比较复杂了.

由于其他的的原因一直没有进一步修改, 有时间一定好好写一段...
作者: pengfei     时间: 2006-10-13 23:38
昨天晚上加班改进了乘法运算脚本, 可以运算整数和浮点数, 通用各种情况. 因为牵涉到大量的取位运算, 所以效率不是很高, 有时间再好好优化一下.

欢迎大家测试...
@echo off
if not %1*==* set M=%1 & set N=%2 & goto jmp
:input
cls
set M=
set N=
set /p M=   input primary number [X]:
set /p N=input number two number [Y]:
:jmp
set sign=
if "%M:~0,1%"=="-" (
    if "%N:~0,1%"=="-" (
        set M=%M:~1%
        set N=%N:~1%
        goto begin
    )
)
if "%M:~0,1%"=="-" (
    set M=%M:~1%
    set sign=-
    goto begin
)
if "%N:~0,1%"=="-" (
    set N=%N:~1%
    set sign=-
)
:begin
echo %M% | find "." >nul || set M=%M%.0
echo %N% | find "." >nul || set N=%N%.0
if "%M:~-1%"=="." set M=%M%0
if "%N:~-1%"=="." set N=%N%0
if "%M:~0,1%"=="." set M=0%M%
if "%N:~0,1%"=="." set N=0%N%
call :jerque "%M%"
call :jerque "%N%"
setlocal enabledelayedexpansion
for /f "tokens=1,2 delims=." %%i in ("%M%") do (
    set X=%%i
    set X_=%%j
)
for /f "tokens=1,2 delims=." %%i in ("%N%") do (
    set Y=%%i
    set Y_=%%j
)
call :front %X%
set X=%front_%
call :front %Y%
set Y=%front_%
call :rear %X_%
set X_=%rear_%
call :rear %Y_%
set Y_=%rear_%
call :count %X_%
set jlxs=%count_%
call :count %Y_%
set /a jlxs=%count_%+%jlxs%
set son=@%Y%%Y_%
set result=0
set append=
:boss
if not "%son:~-1%"=="@" (
    set xx=!son:~-1!
    set son=!son:~0,-1!
    call :under
    call :plus
    set result=!ll!
    set append=0!append!
    goto boss
)
if "%jlxs%"=="0" goto end
set result=!result:~0,-%jlxs%!.!result:~-%jlxs%!
call :rear %result%
set result=%rear_%
if "%result:~-1%"=="." set result=%result:~0,-1%
if "%result:~0,1%"=="." set result=0%result%
:end
cls
echo ============
echo 运算结果^^^!
echo ============
echo.
echo.
echo %M%*%N%=%sign%%result%
pause >nul
exit

:plus
set weave=%single:~0,-1%%weave:~0,-1%
call :count %weave%%append%
set num1=%count_%
call :count %result%
set num2=%count_%
set /a num=%num1%-%num2%
call :join %num% %result%
set result=%join_%
set lx=@%weave%%append%
set ly=@%result%
set ln=0
set ll=
:plus_
set /a lz=%lx:~-1%+%ly:~-1%+%ln%
set/a ln=0%lz:~0,-1%
set ll=%lz:~-1%%ll%
set lx=%lx:~0,-1%
set ly=%ly:~0,-1%
if "%lx%"=="@" (
    if "%ln%"=="1" (
        set ll=1%ll%
        goto :eof
    ) else (
        goto :eof
    )
)
goto plus_
:under
set father=@%X%%X_%
set single=0
set weave=
:under_
set note=%single:~0,-1%
if "%note%"=="" set note=0
set weave=%single:~-1%%weave%
if not "%father:~-1%"=="@" (
    set yy=!father:~-1!
    set /a yy=!yy!
    set father=!father:~0,-1!
    call :op
)
goto :eof
:op
set part=!xx!
set part_=!yy!
set /a single=%part%*%part_%+!note!
goto under_
:front
set front_=%1
:front1
if "%front_:~0,1%"=="0" (
    set front_=%front_:~1%
    goto front1
)
goto :eof
:rear
set rear_=%1
:rear1
if "!rear_:~-1!"=="0" (
    set rear_=!rear_:~0,-1!
    goto rear1
)
goto :eof
:count
set count2=%1@
set count_=0
:count1
if not "!count2:~0,1!"=="@" (
    set /a count_+=1
    set count2=!count2:~1!
    goto count1
)
goto :eof
:join
set margin=%1
set join_=%2
:join1
if not "%margin%"=="0" (
    set /a margin-=1
    set join_=0!join_!
    goto join1
)
goto :eof
:jerque
for /f "tokens=1* delims=." %%i in (%1) do (
    echo %%i%%j|findstr "^[0-9]*$">nul || goto error
)
goto :eof
:error
cls
echo ======================
echo 运算数不符合要求^^!
echo ======================
echo.
echo.
echo 请按任意键重新输入...
pause >nul
goto input
[ Last edited by pengfei on 2006-10-15 at 09:35 ]
附件 1: 无限制乘法运算脚本.rar (2006-10-14 09:00, 1.25 K, 下载附件所需积分 1点 ,下载次数: 20)

作者: 不得不爱     时间: 2006-10-14 08:54
CMD功能有限,做除法运算的时候,对整数除法结果的小数部分直接做丢弃处理,但是也有取余的计算,
set/a a=97%7
6
就是取余计算
作者: pengfei     时间: 2006-10-14 09:05
其实对于批处理做除法运算, 我也有一个思路, 只是比较恐惧, 不敢写.

1.  写出来代码会非常复杂.
2.  执行效率会很低. 初步测算一下, 如果除数是几位数, 被除数是二十位. 执行时间很可能会达到几十秒甚至更多.

不知哪位高手出来挑战一下除法运算, 要求像前面的加, 减, 乘运算一样, 可以处理浮点数, 位数不受限制. 我们拭目以待!!!
作者: pengfei     时间: 2006-10-14 09:13
不要认为不可能, 没有什么不可能的, 在我眼里就没有这个词.

用批处理实现无限制除法运算是完全可行的~~~!
作者: namejm     时间: 2006-10-14 09:15


  Quote:
Originally posted by qwe1234567 at 2006-10-14 08:54:
CMD功能有限,做除法运算的时候,对整数除法结果的小数部分直接做丢弃处理,但是也有取余的计算,
set/a a=97%7
6
就是取余计算

  虽然有模运算,并且可以把结果表示成 商……余数 的格式,但那只是针对整数而言。如果按照浮点数加法运算的模式,按位来做除法,那小数除法的算法又该如何写呢?即使算法能写出来,恐怕也是相当复杂而效率又比较低下的吧?
作者: 不得不爱     时间: 2006-10-14 09:41
象打算盘一样计算就是了
作者: vkill     时间: 2006-10-16 00:31
代码更新在86楼,欢迎继续测试

[ Last edited by he200377 on 2006-10-17 at 01:00 ]
作者: 不得不爱     时间: 2006-10-16 01:05
错误还挺多的,3.2/0.32 和0.32/0.032无法算!
作者: vkill     时间: 2006-10-16 02:10


  Quote:
Originally posted by qwe1234567 at 2006-10-16 01:05:
错误还挺多的,3.2/0.32 和0.32/0.032无法算!

我想个解决根本的方法,呵呵,算之前把小数的位数搞一样,呵呵,问题就好解决多了

[ Last edited by he200377 on 2006-10-16 at 02:11 ]
作者: 不得不爱     时间: 2006-10-16 06:24
那就好!
作者: pengfei     时间: 2006-10-16 08:11


  Quote:
Originally posted by he200377 at 2006-10-16 02:10:

我想个解决根本的方法,呵呵,算之前把小数的位数搞一样,呵呵,问题就好解决多了

[ Last edited by he200377 on 2006-10-16 at 02:11 ]

he200377兄81楼的代码一定花了不少心思, 呵呵~ 不错.

但在运算浮点数时有很大的局限性, 这里提几点不成熟的建议, 也不知分析得是否正确:

1.  生成ver_.txt临时文件, 这个只要把变量用好一点, 完全不用产生临时文件.

2.  看了去零的那段子函数, 你用了二十行, 其实几行就可以解决了.

3.  最大的缺陷就是你说的9.99/9, 看了你的代码, 在这点上考虑得不全面. 出错主要在去掉除数与被除数时的小数点进位. 在最后小数点进位时, 无论%x_wei%是什么值你都采取0.xxx这样的方式进位. 整数本来为正数, 小数点进位时整数位就成了小数.
这里你说的把小数位先对齐再计算也是一个好主意, 但原本就只可以运算9位以内的数, 这样运算范围会变得更小. 不是一个好的解决方案.
建议你在最后把运算结果的小数点位置读取出来, 再根据%x_wei%来进位. 如果位数不足再补零.

4.  qwe1234567版主说的3.2/0.32 和0.32/0.032无法算!当除数的整数为零时出错很严重, 在最后处理小数点时出现了死循环.

5.  0.123/123=0.002609756097 这里在读取被除数时产生了错误, 字符被倒置.

这个算法还不成熟, 而且有局限性, 最重要是不能突破位数的限制.

但处理整数时却可以提高精度.

兄弟还得继续努力, 要想突破位数限制这个算法是无法实现的.

[ Last edited by pengfei on 2006-10-16 at 08:20 ]
作者: vkill     时间: 2006-10-17 01:00
更新在91楼

[ Last edited by he200377 on 2006-10-18 at 05:54 ]
作者: vkill     时间: 2006-10-17 01:01
呵呵,其实做运算,我认为把 cmd 能做的事情交给它做还是能很大的提高效率的,呵呵
作者: vkill     时间: 2006-10-17 01:05
回pengfei兄:

1.  生成ver_.txt临时文件, 这个只要把变量用好一点, 完全不用产生临时文件.
这点我也考虑过,我之所以没有那样做,是考虑到了通用性,你没有发现每个call 都可以完全移植吗?呵呵

2.  看了去零的那段子函数, 你用了二十行, 其实几行就可以解决了.
呵呵~我是这样想的,把几行的放出来show ,哈哈~共同学习吗

[ Last edited by he200377 on 2006-10-17 at 01:06 ]
作者: 不得不爱     时间: 2006-10-17 02:38
还要改进,请看结果:
运算结果:
1321.1321/.132=86348.503267973
91.3/0.91=480.526315789
0.965/9.6=0.05927083333
0.0986/9.86=0.006987829614
作者: pengfei     时间: 2006-10-17 03:08


  Quote:
Originally posted by he200377 at 2006-10-17 01:05:
回pengfei兄:

1.  生成ver_.txt临时文件, 这个只要把变量用好一点, 完全不用产生临时文件.
这点我也考虑过,我之所以没有那样做,是考虑到了通用性 ...

关于生成临时文件和去零, 你可以参考前面的脚本, 这样的代码都有.
作者: vkill     时间: 2006-10-18 05:57
欢迎继续测试~
@echo off
title 批处理除法运算脚本    by:Ye - *    bbs.cn-dos.net
:start
cls   
call :del.bat  
echo.                          
echo  bbs.cn-dos.net
echo --------------------------------------------------------------------------------
echo  程序用途: 两个数的除法运算,被除数和除数都可以是小数
echo  使用说明: 1.被除数或除数的整数位和小数位之和最多9位,超过可能会出错
echo              不过通过下面这个例子,原理上被除数可以计算到任意位:
echo              789/9=(7/9)的值补00+(8/9)的值补0+9/9
echo            2.被除数或除数可简写输入,输入下面这些都可以执行: 9. or .9
echo            3.任何位置输入 ^&、^"、^<、^>、^|、空格 中的任何一个都会引起错误
echo            4.如果出现"无效数字。数字精确度限为 32 位",是位数太多了,结果无效
echo --------------------------------------------------------------------------------
set num1_k=
set /p num1_k= 输入被除数:
if [%num1_k%]==[] goto start
:: 判断是否为纯数字
call :pan_c_num %num1_k%
:: 判断是否输入两个以上的.
call :q_wei %num1_k%

set num2_k=
set /p num2_k=   输入除数:
if [%num2_k%]==[] goto start
call :pan_c_num %num2_k%
call :q_wei %num2_k%

set num1=%num1_k%
set num2=%num2_k%

:: 判断常见的几种情况
if %num2%==0 (echo  错误:除数不可以为0&pause>nul&goto start)
if %num1%==0 (set zhi=0& goto show)
if %num1%==%num2% (set zhi=1& goto show)
if %num1%==. (set zhi=0& goto show)
if %num2%==. (echo  错误:除数不可以为.&pause>nul&goto start)

:: 为.xx xx.和xx补全
>var_.txt echo %num1%
find "." var_.txt>nul&& (if %num1:~0,1%==. set num1=0%num1%
                         if %num1:~-1,1%==. set num1=%num1%0)||set num1=%num1%.0
>var_.txt echo %num2%
find "." var_.txt>nul&& (if %num2:~0,1%==. set num2=0%num2%
                         if %num2:~-1,1%==. set num2=%num2%0)||set num2=%num2%.0

:: 算全部的位数
call :q_wei %num1%
set n1_wei=
set /p n1_wei=<var_.txt
call :q_wei %num2%
set n2_wei=
set /p n2_wei=<var_.txt

:: 算小数点以后的位数
call :x_wei %num1% %n1_wei%
set x1_wei=
set /p x1_wei=<var_.txt
set /a x1_wei=x1_wei-1
call :x_wei %num2% %n2_wei%
set x2_wei=
set /p x2_wei=<var_.txt
set /a x2_wei=x2_wei-1

:: 比较小数位大小,并补小数位到位数相同
if %x1_wei%==%x2_wei% goto wei_t
set max_wei=%x1_wei%
if %max_wei% lss %x2_wei% (set max_wei=%x2_wei%)
set /a bu1_wei=%max_wei%-%x1_wei%
set /a bu2_wei=%max_wei%-%x2_wei%
if %bu1_wei%==0 goto bu_w1_ok
    call :bu_xwei %bu1_wei%
    set x1_wei_0=
    set /p x1_wei_0=<var_.txt
    set num1=%num1%%x1_wei_0%
:bu_w1_ok
if %bu2_wei%==0 goto bu_w2_ok
    call :bu_xwei %bu2_wei%
    set x2_wei_0=
    set /p x2_wei_0=<var_.txt
    set num2=%num2%%x2_wei_0%
:bu_w2_ok
:wei_t
set x_wei=0

:: 去除.
set num1=%num1:.=%
set num2=%num2:.=%

:: 算新的全部的位数
call :q_wei %num1%
set n1_xwei=
set /p n1_xwei=<var_.txt
call :q_wei %num2%
set n2_xwei=
set /p n2_xwei=<var_.txt

:: 位数大于8无法计算,这里,因为set /a 好象最大可以计算到8888888/9999999
if 8 LEQ %n1_xwei% (echo 数字位数太多,暂时计算不了&pause>nul&goto start)
if 8 LEQ %n2_xwei% (echo 数字位数太多,暂时计算不了&pause>nul&goto start)

:: 第一位如果是0就去除
if %num1:~0,1%==0 (
          call :qu_0 %num1% %n1_xwei%
          set num1=
          set /p num1=<var_.txt
                   )

if %num2:~0,1%==0 (
          call :qu_0 %num2% %n2_xwei%
          set num2=
          set /p num2=<var_.txt
                   )

:: 这是防止输入0.0 0.00 等 00 000 等=0的数字而无法执行程序
:: 因为当某个数为0时,第一位如果是0就去除,这样这个数就是空了,写入文件的时候为"ECHO 处于关闭状态。"
>var_.txt echo %num1%
find "关闭状态" var_.txt>nul&&(set zhi=0& goto show)
>var_.txt echo %num2%
find "关闭状态" var_.txt>nul&&(echo  错误:除数不可以为0&pause>nul&goto start)

:: 比较大小,1>2才继续运行
:fc_
if %num1% GEQ %num2% goto fc_ok
                          set /a num1=%num1%*10
                          set /a x_wei=x_wei+1
                          goto fc_
:fc_ok

:: 开始计算
call :jisuan %num1% %num2%
set zhi=
set /p zhi=<var_.txt

:: 开始补小数位
if %x_wei%==0 goto show

:: 去除值中的.
set zhi_=
set zhi_=%zhi:.=%

if %x_wei%==1 (
          set zhi_=
          set zhi=0.%zhi_%
          goto show
              )

:: 其余就是%x_wei%大于1的情况
set /a x_wei-=1
call :bu_xwei %x_wei%
set zhi_bu=
set /p zhi_bu=<var_.txt
set zhi=
set zhi=0.%zhi_bu%%zhi_%
   
goto show
:: 显示结果
:show
call :del.bat
echo --------------------------------------------------------------------------------
echo  运算结果:
echo  %num1_k%/%num2_k%=%zhi%
echo --------------------------------------------------------------------------------
echo                                                           按任意键继续计算......&pause>nul&goto start

:: $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

:q_wei
set var=
set var=%1
setlocal ENABLEDELAYEDEXPANSION
set n=0
set d_geshu=0
:start_a
set "var_=!var:~%n%,1!"
if "%var_%" == "" goto end_a
:: 记录点的个数
if [%var_%]==[.] set /a d_geshu=d_geshu+1
set /a n=n+1
goto start_a
:end_a
>var_.txt echo %n%
:: 判断.的个数,有两个以上的.退出
if %d_geshu% gtr 1 (echo  错误:被除数或除数只可以由数字和一个.组成&pause>nul&goto start)
goto :eof

:del.bat
if exist var_.txt del /q var_.txt>nul
goto :eof

:x_wei
setlocal ENABLEDELAYEDEXPANSION
set var=
set var=%1
set n=0
:start_b
set "var_=!var:~-%n%,1!"
if "%var_%"=="." goto end_b
set /a n=n+1
if %n%==%2 goto end_b
goto start_b
:end_b
>var_.txt echo %n%
goto :eof

:jisuan
set var1=
set var2=
set n=0
set zhi_x=
set var1=%1
set var2=%2
:start_c
if %var1%==0 goto end_c
set /a zhi=%var1%/%var2%
set /a var1=(var1-%var2%*%zhi%)*10
set /a n=n+1
if %n%==2 (set zhi_x=%zhi_x%.%zhi%) else (set zhi_x=%zhi_x%%zhi%)
:: 这里的if %n%==10是算10次,为了算的更精确,可以设置更大
if %n%==10 goto end_c
goto start_c
:end_c
>var_.txt echo %zhi_x%
goto :eof

:bu_xwei
set var=
set var=%1
set wei=
set n=0
:start_d
set /a n=n+1
set wei=%wei%0
if %n%==%var% goto end_d
goto start_d
:end_d
>var_.txt echo %wei%
goto :eof


:qu_0
set var=
set var=%1
setlocal ENABLEDELAYEDEXPANSION
set n=0
set shu=
:start_e
set "var_=!var:~%n%,1!"
if not "%var_%"=="0" goto end_e
set /a n=n+1
goto start_e
:end_e
:start_e_1
set "var_=!var:~%n%,1!"
set shu=%shu%%var_%
set /a n=n+1
if %n%==%2 goto end_e_1
goto start_e_1
:end_e_1   
>var_.txt echo %shu%
goto :eof

:pan_c_num
:: 判断是否为纯数字,先替换了.为空
set var_=%1
set var_=%var_:.=%
>var_.txt echo %var_%
findstr "^[0-9]*$" var_.txt>nul||(echo  错误:被除数或除数只可以由数字和一个.组成&pause>nul&goto start)
goto :eof

作者: 不得不爱     时间: 2006-10-19 08:56
你这个脚本是支持几位数的计算?
输入被除数:99.66666
  输入除数:9.966666
数字位数太多,暂时计算不了
作者: yfd11     时间: 2006-10-19 10:07
思路:
两数字长度有限:
FOR /L %%i IN (start,step,end) DO if "%num1:~"%%i",1" == "".""set set num1=%%i
得到小数点位置.
很多或未知,用循环即.
set /a i=0
:start
if "%num1:~"%%i",1" == "".""set set num1小数点位置=%%i &goto :end &::find用XP好像是外部命令
set /a i+=1
goto :start
得到两数字的小数点位置.
从小数点开始顺环计算整数部分.
如:
set /a k=num1小数点位置
set /a j=num2小数点位置
:start1
if %num1:%k%,1% =="" set num11=0
if %num2:%j%,1% =="" set num22=0
set /a num11=%num1:%k%,1%
set /a num22=%num2:%j%,1%
set /a Valu=num11+num22
set /a  k+=1 &set /a  j+=1
if if %num1:%k%,1% ==""  if %num2:%j%,1% =="" else :goto :end1
同理处理小数点后的位数.
再用ECHO输出
上的%num2:%j%,1% 中间变量能否用ALT+8来做计算没测试.
作者: vkill     时间: 2006-10-19 21:27


  Quote:
Originally posted by qwe1234567 at 2006-10-19 08:56:
你这个脚本是支持几位数的计算?
输入被除数:99.66666
  输入除数:9.966666
数字位数太多,暂时计算不了

里面我设置了小于7,可以取消看看
作者: yfd11     时间: 2006-10-20 01:27
rem 测试系数是WINXPSP2
::C:\>ver
::
::Microsoft Windows XP [版本 5.1.2600]
@echo off
set asicc=智123445679890弱ceho
%asicc:~-3,1%%asicc:~-4,1%%asicc:~-2% %asicc:~-5,1%%asicc:~0,1%制作:QQ%asicc:~4,2%%asicc:~1,1%%asicc:~6,1%%asicc:~5,1%%asicc:~-6,1%%asicc:~2,1%%asicc:~3,1%%asicc:~12,1%
set /p num1=请输入数字1:
set /p num2=请输入数字2:
::set num1=%num1%00&set num2=%num2%00

REM 得到num1,num2小数点位置
set /a i=0
:start1
call set num11=%%num1:~%i%,1%%&call set num22=%%num2:~%i%,1%%
::echo %num11% ,,,,,%num22%,,,,%num111%,,,,%num222% &pause
if "%num11%" == "." set n1=%i%&set a1=true
if "%num22%" == "." set n2=%i%&set a2=true
if "%a1%" == "true" if "%a2%" == "%a1%" goto :next2
set /a i+=1
goto :start1

:next2
echo 结束 小数点1位置%n1% ,,,,小数点2位置%n2%,,,num1=%num1%,,,num2=%num2%
Rem  得到小数部分的数字两数相加的结果
set/a a1=n1&set /a a2=n2&::a1,a2这里又用来
::echo a1=%a1% n1=%n1% a2=%a2% n2=%n2%
set /a value=0
:start2
set/a n1+=1&set /a n2+=1
call set t1=%%num1:~%n1%,1%%&call set t2=%%num2:~%n2%,1%%
::echo t1=%t1% t2=%t2%
if "%t1%" == "" call set value=%value%%%num2:~%n2%%%& goto :next3
if "%t2%" == "" call set value=%value%%%num1:~%n1%%%& goto :next3
set /a tmp1=%t1%+%t2% &set tmp2=%value:~-1%
if "%tmp1:~1,2%" NEQ "" set/a tmp2+=1
::echo tmp2=%tmp2%
set value=%value:~0,-1%%tmp2%%tmp1:~-1%
::echo %value% &pause
goto start2

:next3
set z=%value:~0,1%
echo value=%value%
echo z=%z%
pause
REM 计算整数部分
::set value2=0
:start3
set/a a1-=1&set /a a2-=1
call set t1=%%num1:~%a1%,1%%&call set t2=%%num2:~%a2%,1%%
::echo t1=%t1% t2=%t2%
set /a tmp1=%t1%+%t2%+%z%
if "%tmp1:~1,2%" NEQ "" set/a z=1
set value2=%tmp1:~-1%%value2%
if "%a1%" == "0" call set value1=%%num2:~0,%a2%%%& goto :next4
if "%a2%" == "0" call set value1=%%num1:~0,%a1%%%& goto :next4
::echo value2=%value2% tmp2=%tmp2% z进位=%z% tmp1两数相加结果=%tmp1%&pause
set /a z=0
goto start3

:next4
echo value1=%value1% z=%z% value2=%value2% &pause
REM 计算剩余部分+1的可能
if "%z%" NEQ "1" goto :end
set /a a1=a1-a2
if "%a1:~0,1%" == "-" set a1=%a1:~1%
echo on
:start4
if "%a1%" == "0" goto :end
set /a t1=%a1%
set /a a1-=1
call set tmp1=%%value1:~%a1%,1%%
::echo 取%a1%位置的数%tmp1%
set/a tmp1+=1
call set tmp2=%%value1:~0,%a1%%%
call set i=%%value1:~%t1%%%
echo 0到%a%位置的数%tmp2%
set value1=%tmp2%%tmp1:~-1%%i%
echo value1(加1后结果)=%value1% tmp1(加1的数)=%tmp1% tmp2(1-a1字符)=%tmp2% i从当前到最后字符=%i% &pause
set z=0
if "%tmp1:~1,2%" NEQ "" set z=1&goto :start4
:end
if "%z%"=="0" set z=
echo 结果数是=%z%%value1%%value2%.%value:~1%
%asicc:~-3,1%c%asicc:~-2% 感谢使用本软件有问题请联系QQ:%asicc:~4,2%15%asicc:~4,1%0230
echo 按任意键退出&pause >nul 2>nul

::待测式::晕有太多错误.不过还可能有错误
::长度为SET所能容纳长度.
::程序位数可以加大来循环.就是不用一位一位的算,如二位数与两位数或更大的比较快一点,这里顺环变量是1
::请问楼主,能不能构造程序,来运行自已的程序呢?

[ Last edited by yfd11 on 2006-10-20 at 06:26 ]
作者: electronixtar     时间: 2006-10-20 01:38
2楼的就是用的程序
纯bat化这是为了训练批处理能力
作者: pengfei     时间: 2006-10-20 01:56
不知95楼这段脚本具体实现什么功能, 好像变量出了点问题.
作者: pengfei     时间: 2006-10-20 02:25
讨论了这么久真的有点厌倦了, he200307兄除法运算的算法不够成熟, 而且在一些细节上处理得不够细致, 你的代码没有仔细看. 这里帮你解决最后小数点进位的问题. 代码有点啰嗦.
@echo off
setlocal enabledelayedexpansion
set /p ii=请输入一个浮点数:
set /p pp=请选择小数点需要进的位数:
call :integer %ii%
set one=%num%
set /a ok=one-pp
set "ii=%ii:.=%"
if %pp% lss %one% (
    set result=!ii:~0,%ok%!.!ii:~%ok%!
) else (
    call :plus %ok:~1%
    set result=0.!ii:~0,%ok:~1%!!ii:~%ok:~1%!
)
echo 进位结果=%result%
pause
goto :eof

:integer
set temp=%1
:integer_
if not "%temp:~0,1%"=="." (
    set /a num+=1
    set temp=%temp:~1%
    goto integer_
)
goto :eof
:plus
for /l %%i in (1,1,%1) do (
    set ii=0!ii!
)
goto :eof
[ Last edited by pengfei on 2006-10-21 at 01:14 ]
作者: lxmxn     时间: 2006-10-20 02:33


  Quote:
Originally posted by electronixtar at 2006-10-20 01:38:
2楼的就是用的程序
纯bat化这是为了训练批处理能力

严重同意此观点。

  redtek兄发的这两个主题都是锻炼我们批处理能力的。

作者: 不得不爱     时间: 2006-10-20 03:01
95楼代码我在2000里运行就显示些乱七八糟的东西,也不知道什么是结果,你那个代码不是用来计算的吗?
作者: vkill     时间: 2006-10-20 03:40
被除数多少位都可以实现:789/9=(7/9)的值补00+(8/9)的值补0+9/9
除数没有想到好方法
作者: 不得不爱     时间: 2006-10-20 05:06
我也来个除法运算脚本,经过我的测试是没有问题,请大家测试:
@echo off
cls
title 中国DOS联盟论坛 qwe1234567制作
color 17
setlocal enabledelayedexpansion
if not %1*==* (set num1=%1&if not %2*==* (set num2=%2&goto jmp) ELSE goto err)
:input
set num1=
set num2=
echo                                     实 数 除 法 运 算 脚 本
echo.
echo                  该脚本理论上可以对被除数是N位除数是8位以内的实数进行除法运算
echo.
echo                 注意: 除阿拉伯数字外, 第一位允许输入符号"-", 以及最多一个"."号,
echo                          不允许输入其他字符。否则, 都将视为错误输入...
echo.
echo                                                 中国DOS联盟论坛 qwe1234567制作
set/p num1=请输入被除数:
set/p num2=请输入除数:
:jmp
set fh1=
set fh2=
set fh=
if %num1%*==* goto err
if %num2%*==* goto err
if %num1:~0,1%==- set fh1=-&set num1=%num1:~1%
if %num2:~0,1%==- set fh2=-&set num2=%num2:~1%
if %fh1%*==-* (if %fh2%*==* set fh=-) else if %fh2%*==-* set fh=-
set err=0
echo %num1%|find ".">nul&&set num1=0%num1%0
call :qc %num1% num1
echo %num2%|find ".">nul&&set num2=0%num2%0
call :qc %num2% num2
if %err%==1 goto err
for /f "tokens=1* delims=." %%a in ("%num1%") do (set o1=%%a
set t1=%%b)
for /f "tokens=1* delims=." %%a in ("%num2%") do (set o2=%%a
set t2=%%b)
call :qs0 %o1%
set o1=%sw%
call :qs0 %o2%
set o2=%sw%
call :qw0 %t1%
set t1=%sw%
call :qw0 %t2%
set t2=%sw%
if not %t1%==0 (set o3=%o1%.%t1%) else set o3=%o1%
if not %t2%==0 (set o4=%o2%.%t2%) else set o4=%o2%
if %o4%==0 goto err
if %o3%==0 echo 计算结果是0÷%fh2%%o4%=0&goto input
call :js %t1%
set s1=%sw%
call :js %t2%
set s2=%sw%
If %s1% geq %s2% (set/a s3=s1-s2
call :j0 !s3! %t2%
set t2=!sw!
) ELSE (set/a s3=s2-s1
call :j0 !s3! %t1%
set t1=!sw!)
set tmp1=%o1%%t1%
set tmp2=%o2%%t2%
call :qs0 %tmp2%
set tmp2=%sw%
call :js %sw%
set s2=%sw%
call :qs0 %tmp1%
set tmp1=%sw%
call :js %sw%
set s1=%sw%
set/a zsw=s1-s2
call :qw0 %tmp2%
set tmp2=%sw%
call :js %sw%
set s2=%sw%
if %s2% GTR 8 echo 超出计算范围了!!&GOTO input
set tmp1=%tmp1%00000000000000000000000000000000000000000
set sw=!tmp1:~0,%s2%!
if %sw% geq %tmp2% set/a zsw+=1
set sw=%tmp1:~0,9%
set sw1=%tmp1:~9%
set jg=
:ksjs
set/a jg0=sw/tmp2
set/a sw=sw%%tmp2*10+%sw1:~0,1%
set sw1=%sw1:~1%
set jg=%jg%%jg0%
if not %sw1%.==. goto ksjs
if %zsw% lss 1 (for /l %%c in (0,-1,!zsw!) do set jg=0!jg!) else goto jxs
set o1=%jg:~0,1%
set o2=%jg:~1%
goto xs
:jxs
set o1=!jg:~0,%zsw%!
set o2=!jg:~%zsw%!
:xs
call :qw0 %o2%
set o2=%sw%
if %o2%==0 (set jg=%o1%) else set jg=%o1%.%o2%
echo 计算结果是:
echo %fh1%%o3%÷%fh2%%o4%=%fh%%jg%
pause
cls
goto input

:qs0
set sw=%1
:qs1
if %sw%==0 goto :eof
if %sw:~0,1%==0 set sw=!sw:~1!&goto qs1
goto :eof
:qw0
set sw=%1
:qw1
if %sw%==0 goto :eof
if %sw:~-1%==0 set sw=!sw:~0,-1!&goto qw1
goto :eof
:js
set sw=0
set sw1=%1
if %sw1%==0 set sw=1&goto :eof
:js1
if not %sw1%*==* set sw1=%sw1:~1%&set/a sw+=1&goto js1
goto :eof
:qc
echo %1|find ".">nul||set %2=%1.0
for /f "tokens=1* delims=." %%i in ("%1") do echo %%i%%j|findstr "^[0-9]*$">nul||set err=1
goto :eof
:j0
set sw=%2
if %1==0 goto :eof
for /l %%c in (1,1,%1) do set sw=!sw!0
goto :eof
:err
echo 你输入了非法字符或者除数是0!
echo 请重新输入...
goto input

作者: 不得不爱     时间: 2006-10-20 05:08
计算结果是保留40位小数
作者: vkill     时间: 2006-10-20 05:21
qwe1234567 斑竹 加点说明哈~要么说说思路哈~
作者: 不得不爱     时间: 2006-10-20 05:35
那我大概说下:
1:检查错误与符号
2:小数点对齐
3:计算整数的位数
4:被除数尾数上加41个0
5:除数尾数去0
6:开始计算
7:确定小数点的位置
8:输出结果
作者: vkill     时间: 2006-10-20 05:39
C:\>set/a a=999999999999999999999/8
无效数字。数字精确度限为 32 位。

我在想被除数尾数上加41个0,不是位数更多?还可以计算?为什么?
作者: 不得不爱     时间: 2006-10-20 07:10
被除数尾数上加41个0是为了输出小数加的,我那个脚本可以就是上千位的被除数,不信你自己试下
作者: pengfei     时间: 2006-10-21 00:43
看了一下102楼qwe1234567版主的代码, 写的很不错, 吸取了前面的精华, 把he200377兄的为了提高精度在后面加零反复计算的方案改成了被把除数除完9位再一位一位的取出来算. 因此突破了被除数的位数限制. 在一些细节方面考虑得更加全面, 比如小数点进位等. 这就是集体智慧的结晶.

要想突破除数位数限制, 需要更加发散的思路. 而我那个非常恐惧的算法一直没有勇气实现他. 可能我真的有点害怕, 害怕他的效率会让你们吓一跳...

[ Last edited by pengfei on 2006-10-21 at 00:45 ]
作者: 不得不爱     时间: 2006-10-21 02:29
要想突破除数位数限制, 需要先设计个思路
作者: vkill     时间: 2006-10-21 22:51
突破除数位数限制 我看没有什么好方法,实在想不出了我是
作者: 不得不爱     时间: 2006-10-21 23:01
我到是可以突破除数位数限制,方法正在构思中
作者: vkill     时间: 2006-10-21 23:09


  Quote:
Originally posted by qwe1234567 at 2006-10-21 23:01:
我到是可以突破除数位数限制,方法正在构思中

说说思路哈~方法大家想嘛,哈哈~
作者: redtek     时间: 2006-10-21 23:13
用模拟数组方法?
快说啊~~~:)))
作者: 不得不爱     时间: 2006-10-21 23:20
就是先除,在乘,在减
作者: vkill     时间: 2006-10-21 23:23


  Quote:
Originally posted by qwe1234567 at 2006-10-21 23:20:
就是先除,在乘,在减

还是不明白~
作者: 不得不爱     时间: 2006-10-22 07:07
等我发表了你看下就明白了
作者: pengfei     时间: 2006-10-22 08:34
OK, 看你的作品, 我那个算法虽然突破了位数限制, 但效率太低了.
作者: 不得不爱     时间: 2006-10-23 00:02
经过几天的连续测试和代码优化,终于把可以对N位实数进行除法运算的脚本做出来了,不过除数最好在16位也内,否则等待时间就太长了,除数位数越多等待时间越长!请大家测试。。。。
哎,CMD的运算速度太慢了。。。。
@echo off
cls
title 中国DOS联盟论坛 qwe1234567制作
color 17
setlocal enabledelayedexpansion
if not %1*==* (set num1=%1&if not %2*==* (set num2=%2&goto jmp) ELSE goto 错误)
:输入
set num1=
set num2=
echo                                     实 数 除 法 运 算 脚 本
echo.
echo                        该脚本理论上可以对N位以内的实数进行除法运算
echo.
echo                 注意: 除阿拉伯数字外, 第一位允许输入符号"-", 以及最多一个"."号,
echo                          不允许输入其他字符。否则, 都将视为错误输入...
echo.
echo                                                 中国DOS联盟论坛 qwe1234567制作
set/p num1=请输入被除数:
set/p num2=请输入除数:
:jmp
set fh1=
set fh2=
set fh=
if %num1%*==* goto 错误
if %num2%*==* goto 错误
if %num1:~0,1%==- set fh1=-&set num1=%num1:~1%
if %num2:~0,1%==- set fh2=-&set num2=%num2:~1%
if %fh1%*==-* (if %fh2%*==* set fh=-) else if %fh2%*==-* set fh=-
set err=0
echo %num1%|find ".">nul&&set num1=0%num1%0
call :去错 %num1% num1
echo %num2%|find ".">nul&&set num2=0%num2%0
call :去错 %num2% num2
if %err%==1 goto 错误
for /f "tokens=1* delims=." %%a in ("%num1%") do (set o1=%%a
set t1=%%b)
for /f "tokens=1* delims=." %%a in ("%num2%") do (set o2=%%a
set t2=%%b)
call :去首0 %o1%
set o1=%sw%
call :去首0 %o2%
set o2=%sw%
call :去尾0 %t1%
set t1=%sw%
call :去尾0 %t2%
set t2=%sw%
if not %t1%==0 (set o3=%o1%.%t1%) else set o3=%o1%
if not %t2%==0 (set o4=%o2%.%t2%) else set o4=%o2%
if %o4%==0 goto 错误
if %o3%==0 echo 计算结果是0÷%fh2%%o4%=0&goto 输入
call :计数 %t1%
set s1=%sw%
call :计数 %t2%
set s2=%sw%
If %s1% geq %s2% (set/a s3=s1-s2
call :加尾0 !s3! %t2%
set t2=!sw!
) ELSE (set/a s3=s2-s1
call :加尾0 !s3! %t1%
set t1=!sw!)
set tmp1=%o1%%t1%
set tmp2=%o2%%t2%
call :去首0 %tmp2%
set tmp2=%sw%
call :计数 %sw%
set s2=%sw%
call :去首0 %tmp1%
set tmp1=%sw%
call :计数 %sw%
set s1=%sw%
set/a zsw=s1-s2
call :去尾0 %tmp2%
set tmp2=%sw%
call :计数 %sw%
set s2=%sw%
if %sw% gtr 8 set/a s2=8-sw
set tmp1=%tmp1%0000000000000000000000000000000000000000
set tmp=!tmp1:~0,%sw%!
set sw1=!tmp1:~%sw%!
set jg=
set tmp1=%tmp2:~0,8%
set sw0=!tmp:~0,%s2%!
if %sw% LEQ 8 set/a s2+=1
:开始计算
set/a jg0=sw0/tmp1
:计算
if %jg0%==0 goto 结果
set a1=%tmp2:~-8%
set a2=%tmp2:~0,-8%
set a3=*
set a4=0
set ji=
:乘
if %a1:~0,1%==0 set a1=1%a1%&set a3=1
set/a ji0=jg0*a1+a4
if %a3%==1 set ji=%ji:~-8%
set a4=%ji0:~0,-8%
set ji=%ji0:~-8%%ji%
if %a4%.==. set a4=0
if %a2%.==. goto 减
set a1=%a2:~-8%
set a2=%a2:~0,-8%
goto 乘
:减
if not %a4%==0 set ji=%a4%%ji%
set a1=%tmp%
set jg1=0
set jg2=
:减法
set a2=%a1:~-9%
set a1=%a1:~0,-9%
if not %a1%.==. set a2=1%a2%
set a3=%ji:~-9%
call :去首0 %a3%
set a3=%sw%
set ji=%ji:~0,-9%
set/a jg5=a2-a3+jg1
set/a jg1=0%jg5:~0,-9%-1
if %a1%.==. (if %jg5:~0,1%==- (set jg1==-1) else set jg1=0)
:1
if not %a1%.==. if %jg5:~0,-8%.==. set jg5=0!jg5!&goto 1
set jg2=%jg5:~-9%%jg2%
if %a1%*==* (if %jg1%==-1 (set/a jg0-=1&goto 计算) ELSE set tmp=%jg2%&goto 结果)
goto 减法
:结果
if %sw1%.==. set jg=%jg%%jg0%&goto 显示
set tmp=%tmp%%sw1:~0,1%
call :去首0 %tmp%
set tmp=%sw%
set sw1=%sw1:~1%
set jg=%jg%%jg0%
set sw0=!tmp:~0,%s2%!
goto 开始计算
:显示
if not %jg:~0,1%==0 (set/a zsw+=1)
if %jg:~0,1%==0 set jg=%jg:~1%
if %zsw% gtr 0 goto jxs
for /l %%c in (0,-1,!zsw!) do set jg=0!jg!
set o1=%jg:~0,1%
set o2=%jg:~1%
goto xs
:jxs
set o1=!jg:~0,%zsw%!
set o2=!jg:~%zsw%!
:xs
call :去尾0 %o2%
set o2=%sw%
if %o2%==0 (set jg=%o1%) else set jg=%o1%.%o2%
echo 计算结果是:
echo %fh1%%o3%/%fh2%%o4%=%fh%%jg%
pause
goto :eof

:去首0
set sw=%1
:qs1
if %sw%==0 goto :eof
if %sw:~0,1%==0 set sw=!sw:~1!&goto qs1
goto :eof
:去尾0
set sw=%1
:qw1
if %sw%==0 goto :eof
if %sw:~-1%==0 set sw=!sw:~0,-1!&goto qw1
goto :eof
:计数
set sw=0
set sw1=%1
if %sw1%==0 set sw=1&goto :eof
:js1
if not %sw1%*==* set sw1=%sw1:~1%&set/a sw+=1&goto js1
goto :eof
:去错
echo %1|find ".">nul||set %2=%1.0
for /f "tokens=1* delims=." %%i in ("%1") do echo %%i%%j|findstr "^[0-9]*$">nul||set err=1
goto :eof
:加尾0
set sw=%2
if %1==0 goto :eof
for /l %%c in (1,1,%1) do set sw=!sw!0
goto :eof
:错误
echo 你输入了非法字符或者除数是0!
echo 请重新输入...
goto 输入

作者: 不得不爱     时间: 2006-10-23 00:03
这个脚本的长度是4K。
作者: vkill     时间: 2006-10-23 03:50
qwe1234567版主 这个写的就好多了,哈哈带了说明,看着也不累~顶一个
作者: 不得不爱     时间: 2006-10-23 03:55
呵呵,不是说明,是用了中文的标号,有了中文标号连说明都可以省了!
作者: vkill     时间: 2006-10-23 03:57


  Quote:
Originally posted by qwe1234567 at 2006-10-23 03:55:
呵呵,不是说明,是用了中文的标号,有了中文标号连说明都可以省了!

中文的也可以,还没有试过,不知道中文最多支持几个汉字
作者: 不得不爱     时间: 2006-10-23 04:18
我这也是第一次用中文的标号,我想应该没有个数限制吧
作者: 不得不爱     时间: 2006-10-23 04:19
另外变量也可以是中文
作者: vkill     时间: 2006-10-23 04:31


  Quote:
Originally posted by qwe1234567 at 2006-10-23 04:18:
我这也是第一次用中文的标号,我想应该没有个数限制吧

字母是8个,我想应该有,测试下看看
作者: vkill     时间: 2006-10-23 04:35
还真没有限制,呵呵~以后标号用中文了
作者: 不得不爱     时间: 2006-10-23 04:43
我试了下,在CMD里字母不只8个(估计是没有什么限制吧,或者是255个),你可以用下面的代码测试下
@echo off
:abcdefghi
set /p a=请输入:
if %a%.==5. (goto abcdefghi) else goto abcdefghi1
:abcdefghi1
echo %a%
pause
作者: xycoordinate     时间: 2007-3-4 23:15


  Quote:
Originally posted by namejm at 2006-10-4 21:08:
 到目前为止,各位已经找到了CMD下计算浮点数的两种方法:

  方法一:浮点数的整数部分和小数部分分别计算。实现的过程是:整数部分直接相加即可;小数部分稍微有点麻烦:如果小数部分位数不一致,则要以位数最多的那个数为基准,在另外一个数的小数部分补足0,然后再对小数部分作整数的加法;如果相加的结果位数超过了最长的位数,则要向整数部分进1,小数部分的最高位要相应地减1;

  方法二:把整数部分和小数部分重组成一个新数,再对新数进行加法操作,最后把小数点插入原来的位置;

  两种方法各自的优点和缺点:

  方法一:优点:能处理的浮点数的范围很大,只要相加的结果在 (2^32-1.2^32-1) 和 -(2^32-1.2^32-1)之间,都能处理;缺点:大都出现在小数部分,如:若小数部分最高位为08或09都可能出错,要对这两种情况另作处理;小数部分相加结果的位数长度如果超过最长的位数,则要对整数部分做加1、对小数最高位作减1处理;如果扩充到三个或三个以上的浮点数进行加法操作,则进位的问题将更加复杂;

  方法二:优点:不用另行处理08和09的情况,不用考虑进位的问题(看了楼下pengfei的分析,发现这个地方的描述有点问题,具体情况请参阅楼下的描述);缺点:能处理的浮点数范围比较小,相加结果去掉小数点之后新数值的范围在 (2^32-1.2^32-1) 和 -(2^32-1.2^32-1)之间才能成功。

精彩!!!!

日常用的小数多数是"金额",只有2位小数,用"方法二"比较好!

这个帖子对我的启发很大,谢谢大家!!!



[ Last edited by xycoordinate on 2007-3-4 at 10:51 AM ]
作者: 6622186     时间: 2007-3-10 08:17
若能改为命令行版本(使用时,输入文件名和相应参数) 就太好了.
作者: 6622186     时间: 2007-3-10 09:02
标号也可以用中文, 受教了!
作者: netbenton     时间: 2009-4-5 12:29    标题: 到此一游


@echo off
set aa=%1
set bb=%2

::调用浮点乘法函数
call :mul cc aa bb %3

echo %cc%
goto :eof

:mul
::浮点乘法函数,头尾都可带0,支持乘积为:49位整数,49位小数。
::第一个参数为接收变量名,第二、三个为相乘数变量名,第四个指定要保留小数位数
@echo off&setlocal enabledelayedexpansion
set cc=0
set ka=!%2:*.=!
set kb=!%3:*.=!

set maa=!%2:.=!
set mb=!%3:.=!

for /l %%a in (0,1,49) do if not "!maa:~%%a,1!"=="0" (set maa=!maa:~%%a!&goto :maaok)
:maaok

for /l %%a in (0,1,49) do if not "!mb:~%%a,1!"=="0" (set mb=!mb:~%%a!&goto :mbok)
:mbok

if "!kb!."=="!%3!." set kb=
if "!ka!."=="!%2!." set ka=
set kab=!kb!!ka!#
for /l %%a in (0,1,49) do if "!kab:~%%a,1!"=="#" (set kab=%%a&goto :lp1)

:lp1
if defined mb (set al=!mb:~-4!
if "!al:~0,1!"=="0" set/a al=1!al!-10000
set mb=!mb:~0,-4!
) else (goto :endmul)
set ma=!maa!
set zero=!mz!
set mz=!mz!0000

for /l %%a in (1,1,12) do (
        if defined ma (set bl=!ma:~-4!
                if "!bl:~0,1!"=="0" set/a bl=1!bl!-10000
                set/a bl*=al&set ma=!ma:~0,-4!
        ) else (goto :end1)
        set bl=!bl!!zero!
        set zero=!zero!0000
        call :add cc cc bl
)

:end1
goto :lp1

:endmul
if not %kab%==0 (
set ka=00000000000000000000000000000000000000000000000000%cc%
if "!cc:~0,-%kab%!"=="" (set cc=0.!ka:~-%kab%,%4!) else (set cc=!cc:~0,-%kab%!.!cc:~-%kab%,%4!)
)
endlocal&set %1=%cc%&goto :eof

:add
set xa=%cc%
set xb=%bl%
set cc=
set zz=0
set zy=
for /l %%a in (9,9,81) do (
        if "!xa!!xb!"=="" goto :end
        set cc=!zy!!cc!
if defined xa (set "aa=000000000!xa:~-9!"&set xa=!xa:~0,-9!) else (set aa=000000000)
if defined xb (set "bb=000000000!xb:~-9!"&set xb=!xb:~0,-9!) else (set bb=000000000)
        set/a zz=!zz:~0,-9!+1!bb:~-9!-1000000000+1!aa:~-9!-1000000000
        set zy=000000000!zz!
        set zy=!zy:~-9!
)
:end
set cc=%zz%%cc%
if not %cc% gtr 0 goto :endok
if "%cc:~0,2%"=="0." goto :endok
for /l %%a in (0,1,36) do if not "!cc:~%%a,1!"=="0" (set cc=!cc:~%%a!&goto :endok)
:endok
goto :eof
[ Last edited by netbenton on 2009-4-5 at 10:30 ]
作者: czl1378     时间: 2009-4-5 14:46
4楼的,天书啊。。
但是为什么要在浮点运算上这么深入呢?没见过多少要用到浮点运算的批处理啊。你们这些高手啊,实在太无聊了。
作者: netbenton     时间: 2009-4-7 09:01    标题: 改进了一下


@echo off
set aa=%1
set bb=%2

::调用浮点乘法函数
echo %time%
call :mul cc aa bb %3
echo %time%

echo %cc%
goto :eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
:mul <接收变量名> <被乘数> <乘数> [指定保留小数位]
::
::浮点乘法函数,头尾都可带0,支持乘积为:49位整数,49位小数。
::第一个参数为接收变量名,第二、三个为相乘数变量名,第四个批定要保留小数位数
::最大位数计算仅需12毫秒
::别看代码那么长,速度可不慢
::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@echo off&setlocal enabledelayedexpansion
set cc=0
set ka=!%2:*.=!
set kb=!%3:*.=!

set maa=!%2:.=!
set mb=!%3:.=!

for /l %%a in (0,1,49) do if not "!maa:~%%a,1!"=="0" (set maa=!maa:~%%a!&goto :maaok)
:maaok

for /l %%a in (0,1,49) do if not "!mb:~%%a,1!"=="0" (set mb=!mb:~%%a!&goto :mbok)
:mbok

if "!kb!."=="!%3!." set kb=
if "!ka!."=="!%2!." set ka=
set kab=!kb!!ka!#
for /l %%a in (0,1,49) do if "!kab:~%%a,1!"=="#" (set kab=%%a&goto :lp1)
set mz=
:lp1
if defined mb (set al=!mb:~-4!
if "!al:~0,1!"=="0" set/a al=1!al!-10000
set mb=!mb:~0,-4!
) else (goto :endmul)
set ma=!maa!
set "cl= "
for /l %%a in (1,4,91) do (
        if not defined ma (goto :end1)
        set bl=!ma:~-4!
        if "!bl:~0,1!"=="0" set/a bl=1!bl!-10000
        set/a bl=!cl:~0,-%%a!+bl*al
        set ma=!ma:~0,-4!
        set cl=0000!cl:~-%%a!
        set cl=!bl!!cl:~-%%a!
)
:end1
set cl=%cl:~0,-1%%mz%
set mz=!mz!0000

set xa=%cc%
set xb=%cl%
set cc=
set zz=0
set zy=
for /l %%a in (9,9,81) do (
        if "!xa!!xb!"=="" goto :end2
        set cc=!zy!!cc!
if defined xa (set "aa=000000000!xa:~-9!"&set xa=!xa:~0,-9!) else (set aa=000000000)
if defined xb (set "bb=000000000!xb:~-9!"&set xb=!xb:~0,-9!) else (set bb=000000000)
        set/a zz=!zz:~0,-9!+1!bb:~-9!-1000000000+1!aa:~-9!-1000000000
        set zy=000000000!zz!
        set zy=!zy:~-9!
)
:end2
set cc=%zz%%cc%
if not %cc% gtr 0 goto :lp1
for /l %%a in (0,1,36) do if not "!cc:~%%a,1!"=="0" (set cc=!cc:~%%a!&goto :lp1)
goto :lp1

:endmul
if not %kab%==0 (
set ka=00000000000000000000000000000000000000000000000000%cc%
if "!cc:~0,-%kab%!"=="" (set cc=0.!ka:~-%kab%,%4!) else (set cc=!cc:~0,-%kab%!.!cc:~-%kab%,%4!)
)
endlocal&set %1=%cc%&goto :eof

作者: mmh1     时间: 2009-4-9 00:12
请问下这句什么意思??
if "%number1:~0,1%"=="." set number1=0%number1%
作者: xrw     时间: 2009-5-23 17:47
请问下这句什么意思??
if "%number1:~0,1%"=="." set number1=0%number1%
作者: jlty258     时间: 2009-5-25 11:56
dos只能算整数,算浮点太勉强了
作者: echoair     时间: 2010-5-30 23:40
收藏了,谢谢分享…