找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 23999|回复: 5

[数值计算] 批处理实现全精度浮点连乘

[复制链接]
发表于 2016-9-27 12:16:49 | 显示全部楼层 |阅读模式
本帖最后由 happy886rr 于 2016-9-28 22:25 编辑

[Version:1.1]修正几处变量延迟bug
  纯批处理的计算能力有限,难道真的不能做浮点连乘、大数连乘吗?其实通过模拟构造,批处理完全可以实现函数式语言的计算能力。而且效率也是极佳的。下面是用bat模拟函数式语言,实现全精度浮点连乘。代码经高度优化,修正了同类大数批处理脚本的许多bug,速度也是同类批处理的9倍。无需考虑变量延迟,直接调用:MULTIPLICATION <算式>即可。

  1. @echo off
  2. REM 乘法测试
  3. CALL :MULTIPLICATION 1024×1024×1024
  4. CALL :MULTIPLICATION 9562.36523×1024×1024×1024
  5. CALL :MULTIPLICATION 269.79759569×865.0000003×3636.4236223×7857.0003×5365.6223×5.6223
  6. CALL :MULTIPLICATION 3.56967×3569269.79759569×0.00000000000323656236523×3636.00003264364236223
  7. CALL :MULTIPLICATION 3.1415926535897932384689793238462646535897932384626465358979323846264653589793238462642643383279502886535897932384626465358979323846264653589793238462646535×0.000000000000000765358979323846264653589793238462646535897932384626465358979323846264653589793238462646535897932384626465358979323846264653589793238462646535897932384626897932384626465358979323
  8. PAUSE>NUL
  9. EXIT

  10. def MULTIPLICATION():
  11. {
  12.         :MULTIPLICATION <浮点乘表达式>
  13.         set "expression=%1"
  14.         if "!CHECK_ENABLE_DELAYED_EXPANSION!"=="%CHECK_ENABLE_DELAYED_EXPANSION%" (SETLOCAL) else (SETLOCAL ENABLEDELAYEDEXPANSION)
  15.         set RESULT=1&set "expression=%expression:×= %"
  16.         for %%a in (!expression!) do (
  17.                 CALL :CALCULATE !RESULT! %%a RESULT
  18.         )
  19.         echo 计算%1
  20.         echo =!RESULT!
  21.         ENDLOCAL
  22.         GOTO :EOF
  23. }
  24. def CALCULATE():
  25. {
  26.         :CALCULATE <被乘数> <乘数> [积]
  27.         for /f "tokens=1,2 delims=." %%a in ("%1") do (
  28.                 set A1=%%a&set A=!A1!%%b
  29.                 if "%%b"=="" (set PA=0) else (
  30.                         set A2=%%b
  31.                         for %%i in (512 256 128 64 32 16 8 4 2 1) do (
  32.                                     if not "!A2:~%%i!"=="" (
  33.                                         set/a PA+=%%i
  34.                                         set "A2=!A2:~%%i!"
  35.                                 )
  36.                         )
  37.                         if "!A2:~1!"=="" (set/a PA+=1)
  38.                 )
  39.         )
  40.         for /f "tokens=1,2 delims=." %%a in ("%2") do (
  41.                 set B1=%%a&set B=!B1!%%b
  42.                 if "%%b"=="" (set PB=0) else (
  43.                         set B2=%%b
  44.                         for %%i in (512 256 128 64 32 16 8 4 2 1) do (
  45.                                     if not "!B2:~%%i!"=="" (
  46.                                         set/a PB+=%%i
  47.                                         set "B2=!B2:~%%i!"
  48.                                 )
  49.                         )
  50.                         if "!B2:~1!"=="" (set/a PB+=1)
  51.                 )
  52.         )
  53.         CALL :CUTNUM !A! A NA
  54.         CALL :CUTNUM !B! B NB
  55.         set/a "N=NA+NB,PO=PA+PB"
  56.         for /l %%i in (1 1 !N!) do (
  57.                 for /l %%j in (1 1 %%i) do (
  58.                         set/a j=%%i-%%j+1
  59.                         if defined A[%%j] (
  60.                                 if defined B[!j!] (
  61.                                         set/a sum=A[%%j]*B[!j!]+sum
  62.                                 )
  63.                         )
  64.                 )
  65.                 set/a s=sum+1000
  66.                 set sum=!sum:~0,-3!
  67.                 set pul=!s:~-3!!pul!
  68.         )
  69.         if !PO! equ 0 (
  70.                 for /l %%i in (1 1 10) do (
  71.                         if "!pul:~0,1!"=="0" (
  72.                                 set pul=!pul:~1!
  73.                         )
  74.                 )
  75.                 set "%3=!pul!"
  76.         ) else (
  77.                 set pre=!pul:~0,-%PO%!
  78.                 for /l %%i in (1 1 20) do (
  79.                         if "!pre:~0,1!"=="0" (
  80.                                 set pre=!pre:~1!
  81.                         )
  82.                 )
  83.                 if not defined pre (set pre=0)
  84.                 set "%3=!pre!.!pul:~-%PO%!
  85.         )
  86.         for /l %%i in (1 1 !N!) do (set "A[%%i]="&set "B[%%i]=")&set "pul="&set/a "PA=0,PB=0,PO=0"
  87.         GOTO :EOF
  88. }
  89. def CUTNUM():
  90. {
  91.         :CUTNUM <待切分数> <数据类型> [切分组数]
  92.         set num=%1
  93.         if "!num:~-3!"=="!num:~-4!" (
  94.                 set %2[1]=!num!
  95.                 set %3=1
  96.                 GOTO :EOF
  97.         )
  98.         for /l %%i in (1 1 365) do (
  99.                 if "!num:~0,-3!"=="" (
  100.                         set/a %2[%%i]=!num!
  101.                         set %3=%%i
  102.                         GOTO :EOF
  103.                 )
  104.                 set/a %2[%%i]=1!num:~-3!-1000
  105.                 set num=!num:~0,-3%!
  106.         )
  107.         GOTO :EOF
  108. }
复制代码

评分

参与人数 1PB +6 技术 +1 收起 理由
523066680 + 6 + 1 原来都是跨界达人~ :)

查看全部评分

发表于 2018-3-30 22:40:34 | 显示全部楼层
不知道计算2*0.30会是什么结果
 楼主| 发表于 2018-3-31 09:45:07 | 显示全部楼层
回复 2# zhangzsky
好眼力,那你知道为什么会这样吗?
发表于 2018-3-31 23:05:15 | 显示全部楼层
回复 3# happy886rr


    呵呵,我调用的时候发现的。能力有限无从下手
发表于 2018-5-12 20:01:03 | 显示全部楼层
本帖最后由 Byaidu 于 2018-5-12 20:16 编辑

看得出来楼主的算法能力的确而很强啊,每次发帖都是好长的一段代码,让我看得眼花缭乱……
通过切割数字分段计算来避免溢出是高精度计算的常用方法,求小数点的位置也想到了用倍增法来解决,可以说是精益求精了
不过您这个CUTNUM函数似乎有BUG的样子,没考虑前导零识别为八进制的情况……

CALL :MULTIPLICATION 1×0.10000000011323656236523
CALL :MULTIPLICATION 1×0.90000000011323656236523
返回的却是
=0.08000000011323656236523
无效数字。数字常数只能是十进制(17),十六位进制(0x11)或八进制(021)。
=0.00000000011323656236523

把第93行改成set num=000%1就能解决这个问题,虽然这样会多算一组0*0但对结果应该没有影响

评分

参与人数 1技术 +1 收起 理由
zhangzsky + 1 只能加1分,回头试试

查看全部评分

 楼主| 发表于 2018-5-16 09:26:42 | 显示全部楼层
回复 5# Byaidu
感谢指正,因我初学bat时看到image能显示图片,很好奇,就去研究它是怎么做的,然后就上了C的贼船。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-16 23:02 , Processed in 0.018862 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表