本帖最后由 happy886rr 于 2016-4-5 14:59 编辑
回复 1# 随风
我也写了个批处理大数浮点乘法,任意位,任意小数乘法均可以计算。
全精度浮点乘,批处理的各种特殊性全部考虑,计算效率极佳。
只受限于批处理的输入,批处理最多允许输入一千多位。但是,程序可以扩展。稍加改造即可用多个字符串来存储输入。这样理论上是无限制的。当然最大限制是6300位大数,源于批处理的2的31次方限制。- @echo off&mode con cols=58 lines=38
- :MAIN
- cls
- echo 浮点乘表达式^(乘号用*表示^)
- set /p Express=-^>
- setlocal enabledelayedexpansion
- REM 浮点计数
- for /f "tokens=1,2 delims=*" %%a in ("!Express!") do (
- set A=%%a&set A=!A: =!
- set B=%%b&set B=!B: =!
- )
- for /f "tokens=1,2 delims=." %%a in ("!A!") 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 ("!B!") 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)
- )
- )
- set/a PO=PA+PB
- REM 位数信息
- CALL :CUT !A! A NA
- CALL :CUT !B! B NB
- set/a N=NA+NB,NA*=3,NB*=3
- echo ======================================
- echo 被乘数信息: 有效!NA!位,浮点!PA!位
- echo 乘数信息: 有效!NB!位,浮点!PB!位
- echo ======================================
- set t1=!time:~-5!
- REM 核心乘法
- 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!
- )
- :DIS 显示结果
- if !PO! equ 0 (
- for /l %%i in (1 1 5) do (
- if "!pul:~0,1!"=="0" (
- set pul=!pul:~1!
- )
- )
- echo =!pul!
- ) else (
- set pre=!pul:~0,-%PO%!
- for /l %%i in (1 1 5) do (
- if "!pre:~0,1!"=="0" (
- set pre=!pre:~1!
- )
- )
- if not defined pre (set pre=0)
- echo =!pre!.!pul:~-%PO%!
- )
- REM 毫秒计时器
- set "t2=!time:~-5!" &set/a "t=1!t2:.=!-1!t1:.=!" &if !t! lss 0 (set/a t+=6000)
- set/p=耗时!t:~0,-2!秒!t:~-2!0毫秒
- endlocal&goto MAIN
- :CUT 分割数组
- 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%!
- )
复制代码 测试 615位大数 35486456354... 乘以 312位大数 35867...用时9秒。for循环的效率以及批处理脆弱的计算能力,导致它远远不及C语言(需要0.3秒).
----------------------------------------------------------------------------------------------------------------------------------------------------------------
下面是大整数加法,1000位加1000位范围内,再多,cmd窗口输不进去。效率基本0.0几秒吧。- @echo off&setlocal enabledelayedexpansion
- title By Happy
- mode con cols=65 lines=35
-
- REM 大数长度
- set "MAX=1000" ^位
- REM 分割大小
- set "K=8" ^位
- set /a CYC=MAX/K
- :MAIN
- cls
- echo 请输入^(被加数^)
- set /p A=-^>:
- echo 请输入^(加数^)
- set /p B=-^>:
-
- REM 优化字符
- setlocal
- CALL :POINT !A! A N1
- CALL :POINT !B! B N2
-
- set /a B1=N1*K
- set /a B2=N2*K
- echo ======================================
- echo 被加数信息: 预估!B1!位
- echo 加数信息: 预估!B2!位
- echo ======================================
- echo 计算结果
-
- REM 加法核心
- if !N1! gtr !N2! (set RM=!N1! &set dx=B) else (set RM=!N2! &set dx=A)
- for /l %%i in (1 1 !RM!) do (
- if not defined !dx![%%i] (set "!dx![%%i]=00000000")
- set /a sum=1!A[%%i]!+1!B[%%i]!+sum
- set S=!sum:~-%K%!!S!
- set /a sum=!sum:~0,1!-2
- )
-
- REM 显示
- :DISP
- for /l %%i in (1 1 8) do (if "!S:~0,1!"=="0" (set S=!S:~1!))
- if "!S!"=="" (set S=0)
- echo,!S!
-
- pause>nul
- endlocal
- goto MAIN
-
- REM 分割数位
- :POINT
- set num=%1
- for /l %%i in (1 1 !CYC!) do (
- set %2[%%i]=!num:~-%K%!
- set num=!num:~0,-%K%!
- if "!num!"=="" (
- set /a CU=!%2[%%i]!+100000000
- set %2[%%i]=!CU:~-%K%!
- set /a %3=%%i
- goto :eof
- )
- )
复制代码
|