返回列表 发帖
本帖最后由 523066680 于 2018-12-25 18:54 编辑

回复 24# tigerpower

    现在没动力搞分享了,要写文章还要排版(累)。
附Sublime Text 运行批处理的配置文件(batch.sublime-build)
{
    "cmd": ["$file"],
    "file_regex": ".* at (.*) line ([0-9]*)",
    "selector": "source.dosbatch",
    "encoding": "cp936"
}COPY
默认是F7运行,如果批处理包含中文(GBK编码),安装 GBK Support 插件。
GBK插件参考自 https://jingyan.baidu.com/article/e75aca8555f216142fdac64b.html
[url=][/url]

TOP

本帖最后由 523066680 于 2019-1-4 22:00 编辑

缩进是一种美德

安装 notepad++ ,如果上一行是缩进,按下enter的下一行也会跟着缩进。
sublime_text 则是 括号右边enter自动缩进

没关系,我先写个脚本试试格式化一下缩进的问题,似乎还不需要写parser
use Encode;
use File::Slurp;
STDOUT->autoflush(1);
my $src = read_file( "sample.bat" );
my @lines = split(/\r?\n/, $src);
my $in = 0;
for my $line ( @lines )
{
    if ( $line=~/\)(\s*)$/ ) { $in -= 4; }
    if ( $line=~/\)\s+else\s+\(/ ) { $in -= 4; }
    printf "%s%s\n", " "x$in, $line;
   
    if ( $line=~/\((\s*)$/ ) { $in += 4; }
}COPY
输出:
@echo off&SetLocal EnableDelayedExpansion
color f0
set number=2
rem 设置被开方数(number)(不超过20)(别输入正好能开出来的)
set num=1
rem 输入被开方数的整数部分(num)
echo ------------------------
echo 计算!number!的平方根的值
echo ------------------------
set nun=!num!
set /a bv=!number!-(!num!*!num!)+!num!
set q[4]=0000
set q[2]=00
set q[1]=0
set /p=!num!.<nul
set zz=-5
for /l %%a in (0 1 110) do (
    set /a zz+=6
    set temp=0
    for %%b in (512 256 128 64 32 16 8 4 2 1) do (
        set /a temp+=%%b
        set /a c=%%a/2+1
        set d=!num!
        for /l %%c in (1 1 !c!) do (
            set o=!d:~-6!
            if not defined o set o=0
            for %%f in (4 2 1) do (
                if "!o:~0,%%f!"=="!q[%%f]!" (
                    set o=!o:~%%f!
                    if not defined o set o=0
                )
            )
            set /a "b[%%c]=!o!*!temp!<<1"
            set d=!d:~0,-6!
        )
        set /a y=!temp!*!temp!
        set /a b[1]+=!y!/1000
        for /l %%c in (!c! -1 1) do (
            set /a d=%%c+1
            set /a b[!d!]+=!b[%%c]!/1000000
        )
        set h=!a!
        set a=
        for /l %%c in (1 1 !c!) do (
            if not !c!==%%c (
                set /a b[%%c]=!b[%%c]!%%1000000
                if !b[%%c]! lss 100000 (
                    if !b[%%c]! lss 10000 (
                        if !b[%%c]! lss 1000 (
                            if !b[%%c]! lss 100 (
                                if !b[%%c]! lss 10 (
                                    set b[%%c]=00000!b[%%c]!
                                ) else (
                                    set b[%%c]=0000!b[%%c]!
                                )
                            ) else (
                                set b[%%c]=000!b[%%c]!
                            )
                        ) else (
                            set b[%%c]=00!b[%%c]!
                        )
                    ) else (
                        set b[%%c]=0!b[%%c]!
                    )
                )
            )
            set a=!b[%%c]!!a!
        )
        set z=!b!
        set i=!a:~0,-3!
        if not defined i set i=0
        set x=!nun!
        set /a v=!zz!/9+1
        for /l %%v in (1 1 !v!) do (
            set u=!i:~-9!
            set w=!x:~-9!
            for %%f in (4 2 1) do (
                if "!u:~0,%%f!"=="!q[%%f]!" set u=!u:~%%f!
                if not defined u set u=0
            )
            for %%f in (4 2 1) do (
                if "!w:~0,%%f!"=="!q[%%f]!" set w=!w:~%%f!
                if not defined w set w=0
            )
            set /a k[%%v]=!u!+!w!
            set i=!i:~0,-9!
            set x=!x:~0,-9!
            if not defined i set i=0
            if not defined x set x=0
        )
        for /l %%v in (1 1 !v!) do (
            set /a i=%%v+1
            set /a k[!i!]+=!k[%%v]!/1000000000
        )
        set b=
        for /l %%v in (1 1 !v!) do (
            if not "%%v"=="!v!" (
                set /a k[%%v]=!k[%%v]!%%1000000000
                if !k[%%v]! lss 100000000 (
                    if !k[%%v]! lss 10000000 (
                        if !k[%%v]! lss 1000000 (
                            if !k[%%v]! lss 100000 (
                                if !k[%%v]! lss 10000 (
                                    if !k[%%v]! lss 1000 (
                                        if !k[%%v]! lss 100 (
                                            if !k[%%v]! lss 10 (
                                                set k[%%v]=00000000!k[%%v]!
                                            ) else (
                                                set k[%%v]=0000000!k[%%v]!
                                            )
                                        ) else (
                                            set k[%%v]=000000!k[%%v]!
                                        )
                                    ) else (
                                        set k[%%v]=00000!k[%%v]!
                                    )
                                ) else (
                                    set k[%%v]=0000!k[%%v]!
                                )
                            ) else (
                                set k[%%v]=000!k[%%v]!
                            )
                        ) else (
                            set k[%%v]=00!k[%%v]!
                        )
                    ) else (
                        set k[%%v]=0!k[%%v]!
                    )
                )
            ) else (
                if "!k[%%v]!"=="0" set k[%%v]=
            )
            set b=!k[%%v]!!b!
        )
        set ew=!b:~0,1!
        if !ew! geq !bv! (
            set /a temp-=%%b
            set b=!z!
            set a=!h!
        )
    )
    set /a g=!temp!*!temp!
    set /a g=!g!%%1000
    if !g! lss 100 (
        if !g! lss 10 (
            set nun=!b!!a:~-3!00!g!
        ) else (
            set nun=!b!!a:~-3!0!g!
        )
    ) else (
        set nun=!b!!a:~-3!!g!
    )
    if !temp! lss 100 (
        if !temp! lss 10 (
            set /p=00!temp! <nul
            set num=!num!00!temp!
        ) else (
            set /p=0!temp! <nul
            set num=!num!0!temp!
        )
    ) else (
        set /p=!temp! <nul
        set num=!num!!temp!
    )
    set a=0
    set y=0
    set r=!nun!
)
pause
exit /bCOPY
[url=][/url]

TOP

你们是不是炫技?
写个几百上千行的代码,
然后计算速度10秒一位,有意思?

那我写一个。0.0001秒算完。

添加至bat末尾,调用方法call :s 数字
输出值为变量b和errorlevel
:s
set /a a=%1,b=a/2
for /l %%a in (1,1,15) do set /a b=(b+a/b)/2
exit /b %b%COPY
bug修正版
修正bug版
:s
if "#%1"=="#"  echo 未输入&set b=&exit /b
set /a a=%1,b=a/2
if "%a:~0,1%"=="-" echo 负数&set b=&exit /b
if "%a%"=="0" set b=0&exit /b 0
for /l %%a in (1,1,15) do set /a b=(b+a/b)/2
exit /b %b%COPY
1

评分人数

TOP

本帖最后由 523066680 于 2019-1-5 11:39 编辑

回复 26# SQYSQYSQY

    bat关于计算位数有限制,但是自己采用全套大数加、减、乘、大数比较,就不受这些限制啦。相应的会增加一些消耗。
[url=][/url]

TOP

本帖最后由 523066680 于 2019-1-6 16:29 编辑

回复 31# SQYSQYSQY

     确实很快,在探索算法的层面上,用什么语言都可以探索,所以这点没什么反对的,批处理还可以放大不同算法之间的效率差距。
但是在执行效率上,不能说比的上其他编程语言甚至是编译型语言吧?



我又试了一下 python,10000精度,酸爽
[url=][/url]

TOP

回复 28# SQYSQYSQY


    推荐用 Notepad++ 写代码试试,不用手工敲那么多空格。
2

评分人数

    • SQYSQYSQY: 谢提醒,我又忘了,对不起技术 + 1
    • 523066680: 关键是读代码的人痛苦好吗PB + 6
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

手算开根方案的初步实现,有bug待修,支持大数开根,效率没有很高,先刷新16楼那段代码的时间。
精度80位大约耗时8秒。应该可以再改,再看看吧。
:: Bignum(integer) Square Root, Decimal Solution
:: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Decimal_(base_10)
:: 523066680/vicyang
:: 2019-01
@echo off
setlocal enabledelayedexpansion
:init
    rem 创建用于计算字符串长度的模板,长度限制为 2^pow
    set "sharp=#"
    set /a pow=11, maxlen=1^<^<pow
    for /l %%a in (1,1,%pow%) do set sharp=!sharp!!sharp!
set num=2
rem set num=10
rem call :get_int_of_root %num% int_root cmp
set precision=80
rem call :check_first %num% %precision%
call :decimal_solution %num%
pause
exit /b
:check_first
    perl -Mbignum=p,-%2 -le "print sqrt(%1)" 2>nul
    goto :eof
:: 手算开根方案
:decimal_solution
    setlocal
    set num=%1
    set tnum=%1
    call :length %num% len
    set /a mod=len %% 2, tlen=len, base=0
    if %mod% equ 1 (set /a skip=1) else (set /a skip=2)
    set target=!tnum:~0,%skip%!
    set tnum=!tnum:~%skip%!
    set mp_0=0
    rem prec 精度
    set /a prec = 0
    set /a tbase_len = 0, equ = 0
    :dec_loop
        set /a min=0, max=10, mid=5, range=max-min, quit=0, equ=0
        set /a tbase_len+=1
        call :length %target% target_len
        :: 预估下一个可能的数,并限制二分搜索的最大值
        :guess
        if %target_len% gtr 3 (
        if %target_len% equ %tbase_len% (
            set /a t_head = %target:~0,2%, b_head = %base:~0,2%
        ) else (
            set /a t_head = %target:~0,3%, b_head = %base:~0,2%
        )
        ) else (goto :out_of_guess)
        for /l %%a in (0,1,9) do (
            set /a t = %%a * b_head
            rem echo !t! !target:~0,2! %%a
            if !t! gtr %t_head% (
                set /a max = %%a, mid = ^(min+max^)/2
                goto :out_of_guess
            )
        )
        :out_of_guess
        rem echo, &echo %base%%mid% %target% %tbase_len% %target_len% max: %max%
        :dec_bin_search
            :: mp = [base*10+mid] * mid
            if "%base%" == "0" (
                set /a tbase = mid
            ) else (
                set tbase=!base!!mid!
            )
            set ta=%time%
            call :bignum_mp %tbase% %mid% %tbase_len% 1 mp mp_len
            set mp_%mid%=%mp%
            set mplen_%mid%=%mp_len%
            rem call :cmp %mp% %target% %mp_len% %target_len% cmp
            :: 比较 - 判断是否超出
            :cmp_begin
            if %mp_len% gtr %target_len% (set /a cmp=1&goto :cmp_end)
            if %mp_len% lss %target_len% (set /a cmp=-1&goto :cmp_end)
            :: 如果长度相同,直接按字符串对比
            if "%mp%" gtr "%target%" (set /a cmp=1&goto :cmp_end)
            if "%mp%" lss "%target%" (set /a cmp=-1&goto :cmp_end)
            if "%mp%" equ "%target%" (set /a cmp=0&goto :cmp_end)
            :cmp_end
            rem call :time_delta %ta% %time% bs_tu
            if %cmp% equ 0 (set /a quit=1, equ=1)
            if %cmp% equ 1 (set /a max=mid )
            if %cmp% equ -1 (set /a min=mid )
            if %range% leq 1 ( set /a quit=1 )
            set /a mid=(max+min)/2, range=max-mid
        if %quit% == 0 goto :dec_bin_search
        
        set ta=%time%
        set /p inp="%mid%"<nul
        rem echo, &echo tnum %tnum%, cmp %cmp%, equ %equ%, tg %target%
        if "%tnum%" == "" (
            if %cmp% == 0 (
                goto :dec_loop_out
            ) else (
                rem current precision
                if %prec% equ 0 set /p inp="."<nul
                set /a prec+=1
            )
        )
        rem echo b=%base% tb=%tbase% tg=%target% mp=%mp% mid=%mid%
        call :bignum_minus %target% !mp_%mid%! target
        if %skip% geq %len% (
            set target=%target%00
        ) else (
            if "%target%" == "0" (
                set target=!tnum:~0,2!
            ) else (
                set target=!target!!tnum:~0,2!
            )
            set tnum=!tnum:~2!
            set /a skip+=2
        )
        rem base=base*10+mid*2
        if "%base%" == "0" (
            set /a base=mid*2
        ) else (
            set /a db_mid=mid*2
            call :bignum_plus !base!0 !db_mid! base
        )
        rem call :time_delta %ta% %time% else_tu
    if %prec% leq %precision% (goto :dec_loop)
    :dec_loop_out
    endlocal
    goto :eof
::大数乘法
:bignum_mp
    setlocal
    set num_a=%1
    set num_b=%2
    set /a len_a=%3, len_b=%4
    for /l %%b in ( 1, 1, %len_b% ) do ( set ele_b=!ele_b! !num_b:~-%%b,1! )
    for /l %%a in ( 1, 1, %len_a% ) do ( set ele_a=!ele_a! !num_a:~-%%a,1! )
    set /a id = 0, sid = 0, maxid = 0
    for %%b in ( %ele_b% ) do (
        set /a sid = id, id += 1
        for %%a in ( %ele_a% ) do (
            set /a buff[!sid!] += %%a * %%b, sid += 1, maxid = sid
        )
    )
    rem Merge
    set /a id = 0
    for /l %%c in ( 0, 1, %maxid% ) do (
        set /a next = %%c+1
        set /a buff[!next!] += buff[%%c]/10, buff[%%c] = buff[%%c] %% 10
    )
    if "!buff[%maxid%]!" == "0" set /a maxid-=1
    set product=
    for /l %%n in (%maxid%, -1, 0) do set product=!product!!buff[%%n]!
    endlocal &set %5=%product%&set /a %6=%maxid%+1
    goto :eof
::大数加法
:bignum_plus
    setlocal
    set num_a=%1
    set num_b=%2
    call :length %num_a% len_a
    call :length %num_b% len_b
    set /a max = len_a
    if %len_b% gtr %len_a% (set /a max=len_b, len_b=len_a&set num_a=%num_b%&set num_b=%num_a%)
    for /l %%n in ( 1, 1, %max% ) do (
        if %%n leq %len_b% (
            set /a buff[%%n] = !num_a:~-%%n,1! + !num_b:~-%%n,1!
        ) else (
            set buff[%%n]=!num_a:~-%%n,1!
        )
    )
    set /a id = 0
    for /l %%c in ( 0, 1, %max% ) do (
        set /a next = %%c+1
        set /a buff[!next!] += buff[%%c]/10, buff[%%c] = buff[%%c] %% 10
    )
    if "!buff[%next%]!" gtr "0" set /a max+=1
    set sum=
    for /l %%a in (%max%, -1, 1) do set sum=!sum!!buff[%%a]!
    endlocal &set %3=%sum%
    goto :eof
::大数减法
:bignum_minus
    setlocal
    set num_a=%1
    set num_b=%2
    call :length %num_a% len_a
    call :length %num_b% len_b
    set /a max = len_a
    if %len_b% gtr %len_a% (set /a max=len_b, len_b=len_a&set num_a=%num_b%&set num_b=%num_a%)
    set /a minus = 0
    for /l %%n in ( 1, 1, %max% ) do (
        if %%n leq %len_b% (
            set /a dt = !num_a:~-%%n,1! - !num_b:~-%%n,1! - minus
        ) else (
            set /a dt = !num_a:~-%%n,1! - minus
        )
        if !dt! lss 0 (
            set /a buff[%%n] = dt + 10, minus=1
        ) else (
            set /a buff[%%n] = dt, minus=0
        )
    )
    set delta=#
    for /l %%a in (%max%, -1, 1) do set delta=!delta:#0=#!!buff[%%a]!
    endlocal &set %3=%delta:#=%
    goto :eof
::字符串长度计算
:length %str% %vname%
    setlocal
    set test=%~1_%sharp%
    set test=!test:~0,%maxlen%!
    set test=%test:*_=%
    set /a len=maxlen-(%test:#=1+%1)
    endlocal &set %2=%len%
    goto :eof
:: plp626的时间差函数 时间跨度在1分钟内可调用之;用于测试一般bat运行时间
:time_delta <beginTimeVar> <endTimeVar> <retVar> // code by plp626
    setlocal
    set ta=%1&set tb=%2
    set /a "c=1!tb:~-5,2!!tb:~-2!-1!ta:~-5,2!!ta:~-2!,c+=-6000*(c>>31)"
    if defined %3 set /a c+=!%3!
    endlocal&set %3=%c%
    goto:eofCOPY
[url=][/url]

TOP

本帖最后由 523066680 于 2019-1-5 21:02 编辑

回复 35# SQYSQYSQY

    当我看了 happy886r 的乘法,已经知道划分为N位一段而非逐位的处理可以令速度翻倍。参考23楼 http://bbs.bathome.net/redirect. ... 1557&pid=216162
我当然也知道 for 比 goto 快, goto 比 call 快,但我是不会让我的代码变成这样的。

不过这是批处理,如果我不花时间继续优化,我就可以做别的有趣的事情了。
1

评分人数

    • 老刘1号: bat纠结什么效率,根本没有效率技术 + 1
[url=][/url]

TOP

回复  SQYSQYSQY

     确实很快,在探索算法的层面上,用什么语言都可以探索,所以这点没什么反对的,批 ...
523066680 发表于 2019-1-5 17:26



   这么说的话,我想到一个软件 super pi
百度就有下载。
可以1分钟计算3200万位。

TOP

本帖最后由 523066680 于 2019-1-5 23:07 编辑

回复 24# 小程936

    你是说Pi吗,很多大牛为此做过大的量工作。
传奇人物 Fabrice Ballard
有史以来最优秀的程序员有哪些? - absfree的回答 - 知乎
[url=][/url]

TOP

本帖最后由 523066680 于 2019-1-29 18:46 编辑

nothing
[url=][/url]

TOP

看了下楼主的程序。
330行之前的,换我写不超过100行。
任何重复性代码都应考虑for或if
连err都写五六个标签,有必要?
直接call err 1
:err
if %1==1 (echo ...)
if %1==2 ...
...
exit /b
也行啊?

TOP

最近看此帖, 然后搜索了一些高精度数学运算的资料, 发现深入学习需要高等数学知识, 本人高等数学待学习.

楼主看来近期对此范畴算法有高度兴趣, 所以我建议楼主查看开源软件的实现: GNU多重精度运算库

GNU Multiple Precision Arithmetic Library (GMP), 简称 GMP 是 GNU 的一部分, 并且为 Maple, Mathematica 这些专业数学软件提供 高精度数学运算 的实现

GMP 的平方根算法说明:
https://gmplib.org/manual/Square-Root-Algorithm.html

Paul Zimmermann, “Karatsuba Square Root”, INRIA Research Report 3805, November 1999,
http://hal.inria.fr/inria-00072854/PDF/RR-3805.pdf

任意精度算术软件列表
https://en.wikipedia.org/wiki/List_of_arbitrary-precision_arithmetic_software
1

评分人数

TOP

本帖最后由 523066680 于 2019-1-7 10:11 编辑

优化一波,没你的快。100位5.6秒,300位35秒 (CPU比较好,换一台机可能是8秒和45秒)
仍然使用逐位的计算,未使用连续N位数字为一段的处理方案,省心。

解决的问题:之前的代码对100开根会出现 10.0000000,现在不会了。
优化的部分:去掉了很多临时数组的操作特别是 buff[] 和与之对应的for循环
:: Bignum(integer) Square Root, Decimal Solution
:: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Decimal_(base_10)
:: 523066680/vicyang
:: 2019-01
@echo off
setlocal enabledelayedexpansion
:init
    rem 创建用于计算字符串长度的模板,长度限制为 2^pow
    set "sharp=#"
    set /a pow=11, maxlen=1^<^<pow
    for /l %%a in (1,1,%pow%) do set sharp=!sharp!!sharp!
set precision=80
set num=2
call :check_one %num%
pause
exit /b
:: 独立测试
:check_one
    set ta=!time!
    rem call :check_first %1 !precision!
    call :decimal_solution %1
    call :time_delta !ta! !time! tu
    echo time used: !tu!
    goto :eof
:: 批量测试
:check_all
    for /l %%a in (1,1,99) do (
        echo test number: %%a
        call :check_first %%a !precision!
        call :decimal_solution %%a
        echo,
    )
    goto :eof
:: 使用其他工具校验/对比结果
:check_first
    perl -Mbignum=p,-%2 -le "print sqrt(%1)" 2>nul
    goto :eof
:: 手算开根方案
:decimal_solution
    setlocal
    set num=%1
    set tnum=%1
    call :length %num% len
    set /a mod=len %% 2, tlen=len, base=0
    if %mod% equ 1 (set /a skip=1) else (set /a skip=2)
    set target=!tnum:~0,%skip%!
    set tnum=!tnum:~%skip%!
    set /a mp_0=0, mplen_0=1
    set /a bstimes=0
    rem prec 当前精度
    set /a prec = 0
    set /a base_len=0, equ=0, target_len=skip
    :dec_loop
        set /a min=0, max=10, mid=5, range=max-min, quit=0, equ=0
        set /a tbase_len=base_len+1
        :: 评估二分搜索的最大值
        :guess
        if %target_len% gtr 3 (
        if %target_len% equ %tbase_len% (
            set /a t_head = %target:~0,2%, b_head = %base:~0,2%
        ) else (
            set /a t_head = %target:~0,3%, b_head = %base:~0,2%
        )
        ) else (goto :out_of_guess)
        for /l %%a in (0,1,9) do (
            set /a t = %%a * b_head
            if !t! gtr %t_head% (
                set /a max = %%a
                goto :out_of_guess
            )
        )
        :out_of_guess
        :: 做大致的除法预估 mid 值
        :estimate
        if %target_len% gtr 5 (
            if %target_len% geq %tbase_len% (
                set /a est=!target:~0,6!/!base:~0,5!
                rem echo est - !est!
                set /a mid=!est:~0,1!
                rem echo,&echo %base% !target! !est! !mid! !target:~0,5!/!base:~0,5!
            )
        )
        :: 如果预估max等于1,说明结果只能为0,跳过 bin_search
        if %max% equ 1 (set /a mid=0& goto :out_bin_search )
        rem echo, &echo %base%%mid% %target% %tbase_len% %target_len% max: %max%
        set ta=%time%
        :dec_bin_search
            set /a bstimes+=1
            :: mp = [base*10+mid] * mid
            if "%base%" == "0" (
                set /a tbase = mid
            ) else (
                set tbase=!base!!mid!
            )
            call :bignum_mp_single %tbase% %mid% %tbase_len% 1 mp mp_len
            set mp_%mid%=%mp%
            set mplen_%mid%=%mp_len%
            :: 比较 - 判断是否超出
            :cmp_begin
            if %mp_len% gtr %target_len% (set /a cmp=1&goto :cmp_end)
            if %mp_len% lss %target_len% (set /a cmp=-1&goto :cmp_end)
            :: 如果长度相同,直接按字符串对比
            if "%mp%" gtr "%target%" (set /a cmp=1&goto :cmp_end)
            if "%mp%" lss "%target%" (set /a cmp=-1&goto :cmp_end)
            if "%mp%" equ "%target%" (set /a cmp=0&goto :cmp_end)
            :cmp_end
            rem call :time_delta %ta% %time% bs_tu
            if %cmp% equ 0 (set /a quit=1, equ=1)
            if %cmp% equ 1 (set /a max=mid)
            if %cmp% equ -1 (set /a min=mid)
            if %range% leq 1 ( set /a quit=1 )
            set /a mid=(max+min)/2, range=max-mid
        if %quit% == 0 goto :dec_bin_search
        :out_bin_search
        rem echo, &echo est: %est%, act mid: %mid%
        set /p inp="%mid%"<nul
        if "%tnum%" == "" (
            :: 如果target只剩下 00,方案结束
            if "%target%" == "00" ( goto :dec_loop_out )
            if %cmp% == 0 (
                goto :dec_loop_out
            ) else (
                :: 当前精度
                if %prec% equ 0 set /p inp="."<nul
                set /a prec+=1
            )
        )
        rem echo b=%base% tb=%tbase% tg=%target% mp=%mp% mid=%mid%
        set ta=%time%
        call :bignum_minus %target% !mp_%mid%! %target_len% !mplen_%mid%! target target_len
        if %skip% geq %len% (
            set target=%target%00
        ) else (
            if "%target%" == "0" (
                set target=!tnum:~0,2!
            ) else (
                set target=!target!!tnum:~0,2!
            )
            set tnum=!tnum:~2!
            set /a skip+=2
        )
        set /a target_len+=2
        rem base=base*10+mid*2
        if "%base%" == "0" (
            set /a base=mid*2
            if !base! geq 10 (set /a base_len=2) else (set /a base_len=1)
        ) else (
            set /a db_mid=mid*2
            if !db_mid! geq 10 (set /a dbmidlen=2) else (set /a dbmidlen=1)
            call :bignum_plus !base!0 !db_mid! !base_len!+1 !dbmidlen! base base_len
        )
    if %prec% leq %precision% (goto :dec_loop)
    :dec_loop_out
    echo,
    echo search times: %bstimes%
    endlocal
    goto :eof
:: 大数 乘以 单位数
:bignum_mp_single
    setlocal
    set num_a=%1
    set num_b=%2
    set /a pool = 0, maxid = %3
    set "res="
    for /l %%a in ( 1, 1, %maxid% ) do (
        set /a mp = !num_a:~-%%a,1! * num_b + pool, t = mp %% 10, pool = mp / 10
        set res=!t!!res!
    )
    if %pool% neq 0 (
        set /a maxid+=1
        set res=!pool!!res!
    )
    endlocal&set %5=%res%&set %6=%maxid%
    goto :eof
::大数加法
:bignum_plus
    setlocal
    set num_a=%1
    set num_b=%2
    set /a len_a=%3, len_b=%4
    set /a max = len_a
    if %len_b% gtr %len_a% (set /a max=len_b, len_b=len_a&set num_a=%num_b%&set num_b=%num_a%)
    set /a pool=0
    set res=
    for /l %%n in ( 1, 1, %max% ) do (
        if %%n leq %len_b% (
            set /a t = !num_a:~-%%n,1! + !num_b:~-%%n,1! + pool
        ) else (
            set /a t = !num_a:~-%%n,1! + pool
        )
        set /a mod = t %% 10, pool = t / 10
        set res=!mod!!res!
    )
    if %pool% gtr 0 (set /a max+=1 &set res=1%res%)
    endlocal &set %5=%res%&set %6=%max%
    goto :eof
::大数减法
:bignum_minus
    setlocal
    set num_a=%1
    set num_b=%2
    set /a len_a=%3, len_b=%4
    set /a max = len_a
    if %len_b% gtr %len_a% (set /a max=len_b, len_b=len_a&set num_a=%num_b%&set num_b=%num_a%)
    set /a minus = 0
    set "res="
    for /l %%n in ( 1, 1, %max% ) do (
        if %%n leq %len_b% (
            set /a dt = !num_a:~-%%n,1! - !num_b:~-%%n,1! - minus
        ) else (
            set /a dt = !num_a:~-%%n,1! - minus
        )
        if !dt! lss 0 (
            set /a t = dt + 10, minus=1
        ) else (
            set /a t = dt, minus=0
        )
        set res=!t!!res!
        if !t! equ 0 (set /a zero+=1) else (set /a zero=0)
    )
    set res=!res:~%zero%!
    endlocal &set %5=%res%&set /a %6=%max%-%zero%
    goto :eof
::字符串长度计算
:length %str% %vname%
    setlocal
    set test=%~1_%sharp%
    set test=!test:~0,%maxlen%!
    set test=%test:*_=%
    set /a len=maxlen-(%test:#=1+%1)
    endlocal &set %2=%len%
    goto :eof
:: plp626的时间差函数 时间跨度在1分钟内可调用之;用于测试一般bat运行时间
:time_delta <beginTimeVar> <endTimeVar> <retVar> // code by plp626
    setlocal
    set ta=%1&set tb=%2
    set /a "c=1!tb:~-5,2!!tb:~-2!-1!ta:~-5,2!!ta:~-2!,c+=-6000*(c>>31)"
    if defined %3 set /a c+=!%3!
    endlocal&set %3=%c%
    goto:eofCOPY
1

评分人数

[url=][/url]

TOP

回复 30# SQYSQYSQY

优化效率一时爽,添加功能火葬场。(就目前来说浮点数开根还没搞进去,也没有经过大量的数值测试BUG)
观点:功能完善前写给人看,方便调整,完善后再优化给机器看。

发现自己代码优化后有问题,29 26 开根会出现5.99999,29楼已经纠正,顺便提速,estimate 模块用于提前估值减少二分搜索次数。
在我的主机 80位 3.5s 300位 32s,手算法似乎不怎么需要二分,可以快速判定下一位数,绕了很大的弯路,修改中。
[url=][/url]

TOP

返回列表