本帖最后由 happy886rr 于 2016-9-28 22:25 编辑
[Version:1.1]修正几处变量延迟bug
纯批处理的计算能力有限,难道真的不能做浮点连乘、大数连乘吗?其实通过模拟构造,批处理完全可以实现函数式语言的计算能力。而且效率也是极佳的。下面是用bat模拟函数式语言,实现全精度浮点连乘。代码经高度优化,修正了同类大数批处理脚本的许多bug,速度也是同类批处理的9倍。无需考虑变量延迟,直接调用:MULTIPLICATION <算式>即可。 | @echo off | | | | CALL :MULTIPLICATION 1024×1024×1024 | | CALL :MULTIPLICATION 9562.36523×1024×1024×1024 | | CALL :MULTIPLICATION 269.79759569×865.0000003×3636.4236223×7857.0003×5365.6223×5.6223 | | CALL :MULTIPLICATION 3.56967×3569269.79759569×0.00000000000323656236523×3636.00003264364236223 | | CALL :MULTIPLICATION 3.1415926535897932384689793238462646535897932384626465358979323846264653589793238462642643383279502886535897932384626465358979323846264653589793238462646535×0.000000000000000765358979323846264653589793238462646535897932384626465358979323846264653589793238462646535897932384626465358979323846264653589793238462646535897932384626897932384626465358979323 | | PAUSE>NUL | | EXIT | | | | def MULTIPLICATION(): | | { | | :MULTIPLICATION <浮点乘表达式> | | set "expression=%1" | | if "!CHECK_ENABLE_DELAYED_EXPANSION!"=="%CHECK_ENABLE_DELAYED_EXPANSION%" (SETLOCAL) else (SETLOCAL ENABLEDELAYEDEXPANSION) | | set RESULT=1&set "expression=%expression:×= %" | | for %%a in (!expression!) do ( | | CALL :CALCULATE !RESULT! %%a RESULT | | ) | | echo 计算%1 | | echo =!RESULT! | | ENDLOCAL | | GOTO :EOF | | } | | def CALCULATE(): | | { | | :CALCULATE <被乘数> <乘数> [积] | | for /f "tokens=1,2 delims=." %%a in ("%1") do ( | | set A1=%%a&set A=!A1!%%b | | if "%%b"=="" (set PA=0) else ( | | set A2=%%b | | for %%i in (512 256 128 64 32 16 8 4 2 1) do ( | | if not "!A2:~%%i!"=="" ( | | set/a PA+=%%i | | set "A2=!A2:~%%i!" | | ) | | ) | | if "!A2:~1!"=="" (set/a PA+=1) | | ) | | ) | | for /f "tokens=1,2 delims=." %%a in ("%2") do ( | | set B1=%%a&set B=!B1!%%b | | if "%%b"=="" (set PB=0) else ( | | set B2=%%b | | for %%i in (512 256 128 64 32 16 8 4 2 1) do ( | | if not "!B2:~%%i!"=="" ( | | set/a PB+=%%i | | set "B2=!B2:~%%i!" | | ) | | ) | | if "!B2:~1!"=="" (set/a PB+=1) | | ) | | ) | | CALL :CUTNUM !A! A NA | | CALL :CUTNUM !B! B NB | | set/a "N=NA+NB,PO=PA+PB" | | for /l %%i in (1 1 !N!) do ( | | for /l %%j in (1 1 %%i) do ( | | set/a j=%%i-%%j+1 | | if defined A[%%j] ( | | if defined B[!j!] ( | | set/a sum=A[%%j]*B[!j!]+sum | | ) | | ) | | ) | | set/a s=sum+1000 | | set sum=!sum:~0,-3! | | set pul=!s:~-3!!pul! | | ) | | if !PO! equ 0 ( | | for /l %%i in (1 1 10) do ( | | if "!pul:~0,1!"=="0" ( | | set pul=!pul:~1! | | ) | | ) | | set "%3=!pul!" | | ) else ( | | set pre=!pul:~0,-%PO%! | | for /l %%i in (1 1 20) do ( | | if "!pre:~0,1!"=="0" ( | | set pre=!pre:~1! | | ) | | ) | | if not defined pre (set pre=0) | | set "%3=!pre!.!pul:~-%PO%! | | ) | | for /l %%i in (1 1 !N!) do (set "A[%%i]="&set "B[%%i]=")&set "pul="&set/a "PA=0,PB=0,PO=0" | | GOTO :EOF | | } | | def CUTNUM(): | | { | | :CUTNUM <待切分数> <数据类型> [切分组数] | | set num=%1 | | if "!num:~-3!"=="!num:~-4!" ( | | set %2[1]=!num! | | set %3=1 | | GOTO :EOF | | ) | | for /l %%i in (1 1 365) do ( | | if "!num:~0,-3!"=="" ( | | set/a %2[%%i]=!num! | | set %3=%%i | | GOTO :EOF | | ) | | set/a %2[%%i]=1!num:~-3!-1000 | | set num=!num:~0,-3%! | | ) | | GOTO :EOF | | }COPY |
|