
[原創]通用批處理開平方程序理論上支持任意數字最后由 techon 于 -5-27 19:15廢話一大堆,刪了方法原理見算數開平方法則通用性處理,可支持任意數字輸入,結果保留8-9位有效數字其他算法:二樓 版主的 牛頓迭代法快速求平方根或近似值,只能計算1-214748,保留兩位小數七樓 caruko的 使用二進制位移法開平方,支持1-2147483646,最多保留4位小數代碼如下:保留了部分測試代碼和注釋,歡迎批評指正用法 call :_Sqrt 被開方數字
-----------------------------------------------------------------------------------另附除法計算部分,僅支持整數輸入用法 call :_div 被除數 除數 [保留小數位,如精度不夠則不保留]返回結果 保存在變量quo中例:nclick="copycode($('code0'));">復制代碼
- @echo off
- SETLOCAL ENABLEDELAYEDEXPANSION
- rem 這是測試部分
- set x=1.4233599273013201
- set max=14233599273013201
- rem set Max = 2147483647小于2的31次方-1(2^31=2147483648)32位有符號數可表示的最大值set/a 可處理的最大數(32位系統是這個,64位系統未測試)
- rem 11930464 * 20 * 9 + 9^2 = 214748360111930464^2 = 142335971255296
- rem 119304649119304649^2 = 14233599273013201(可正常開完的最大被開方數)
- rem%1=被開方數這是結果寫在這方便比對
- call :_Sqrt 22500000000001500000
- echo --------jg===%jg%---------&pause
- call :_Sqrt 10000001000
- echo --------jg===%jg%---------&pause
- call :_Sqrt 00
- echo --------jg===%jg%---------&pause
- call :_Sqrt 00000.000000010.0001
- echo --------jg===%jg%---------&pause
- call :_Sqrt 265.0990195135927848300282241090228
- echo --------jg===%jg%---------&pause
- call :_Sqrt %x%1.19304649
- echo --------jg===%jg%---------&pause
- call :_Sqrt %max%119304649
- echo --------jg===%jg%---------&pause
- call :_Sqrt 11112233445643274231572105414578904.64332842651254712323
- echo --------jg===%jg%---------&pause
- call :_Sqrt 2.2500000000000001.5
- echo --------jg===%jg%---------&pause
- call :_Sqrt 0.0000010.001
- call :_Sqrt 01111.564327423157233.340130884913412409133565742286
- call :_Sqrt 10485761024
- call :_Sqrt 0.0130.114895604
- call :_Sqrt 0.000000640.0008
- echo --------jg===%jg%---------&pause
- call :_Sqrt 557.4161984870956629487113974408007
- call :_Sqrt 4.000000002
- echo --------jg===%jg%---------&pause
- rem 做成子程序了,方便調用
- pause&pause
- goto :EOF
- rem 開方程序開始
- :_Sqrt
- SETLOCAL ENABLEDELAYEDEXPANSION
- rem 檢查輸入是否有效
- set a=0&set sr=0&set tmpin=%1
- if !tmpin!== set sr=-1&goto :chkend
- :chkloop
- if !tmpin:~%a%,1!==. (set/a sr+=1&if !sr! gtr 1 set sr=-1&goto :chkend) ^
- else (if !tmpin:~%a%^,1! lss 0 set sr=-1&goto :chkend)&if !tmpin:~%a%^,1! gtr 9 set sr=-1&goto :chkend
- set/a a+=1
- if not !tmpin:~%a%,1!== goto :chkloop
- :chkend
- rem 初始化變量
- set jg=0&set xs=0&set xsl=0&set fxs=0&set of=0&set pl=0&set d=0&set x1=&set x2=&set tlc=
- if %sr% equ -1 ENDLOCAL&set jg=被開方數字非法&echo Call :_Sqrt 輸入的參數無效&goto :EOF
- if %sr% equ 0 (rem 無小數點
- call :_dez l %tmpin% xa
- if !xa!== set xa=0
- ) else (rem 有小數點輸入
- for /f tokens=1,2 delims=. %%C in (0%tmpin%) do (
- call :_dez l %%C
- set x1=!dez!
- call :_dez r %%D
- set x2=!dez!
- rem 處理輸入數 可將 0.xxx 簡略為 .xxx 輸入,取輸入的整數部分為 x1,小數部分為x2
- if !x2!== (rem 沒有小數
- if !x1!== (set xa=0) else set xa=!x1!
- ) else (rem 有小數
- call :_lenc !x2!
- set/a tlc=lenc%%2
- if !tlc! equ 1 set x2=!x2!0
- rem 小數位數如果為奇數,將其后補0,湊為偶數位
- set/a xsl=^(lenc+1^)/2
- rem 輸入小數的位數除以2,開完平方后需要補回的小數位數
- if !x1!== call :_dez l !x2! x2
- set xa=!x1!!x2!
- )
- )
- )
- if %x2%== (rem 如果沒有小數部分,去掉整數低位2n個0,設置小數位數為負
- :lx1
- if !xa:~-2!==00 set xa=!xa:~0,-2!&set/a xsl-=1&goto :lx1
- )
- set j19=0
- for /l %%C in (0,1,9) do (rem 如果是1-9的平方數直接給出結果
- set/a jc=%%C*%%C
- if !xa!==!jc! (
- if %xsl% equ 0 echo 結果=%%C&ENDLOCAL&set jg=%%C&goto :EOF
- set _jg=%%C&set jg=%%C
- :xsub
- if !xsl! lss 0 set jg=!jg!0&set/a xsl+=1&goto :xsub
- :xsad
- if !xsl! gtr 0 set jg=0.!_jg!&set _jg=0!_jg!&set/a xsl-=1&goto :xsad
- set j19=1
- )
- )
- if %j19%==1 echo 結果=%jg%&ENDLOCAL&set jg=%jg%&goto :EOF
- call :_lenc %xa%
- set/a la=lenc%%2
- rem 將xa補位為偶數位
- if %la% equ 1 set xa=0%xa%
- rem 開方循環開始
- :_sqr
- set p=!xa:~%pl%,2!
- if %d% equ 0 (
- if %p%== (
- echo 開方正好開盡^^_^^&goto :_endsqr
- ) else (
- if %jg% gtr 11930464 set of=1&echo 產生溢出!!!&goto :_endsqr
- if !p:~0,1!==0 (set ps=%p:~1,1%) else (set ps=%p%)
- )
- ) else (
- if %jg% gtr 11930464 set of=1&echo 產生溢出!!!&goto :_endsqr
- if %p%== set p=00&set/a xs+=1
- set ps=%d%!p!
- )
- for /l %%C in (9,-1,0) do (
- set/a ts=20*%%C*jg+%%C*%%C
- if !ts! leq %ps% (
- if not %jg%==0 (set jg=%jg%%%C) else set jg=%%C
- set/a d=ps-ts&goto :_sh
- )
- )
- :_sh
- set/a pl+=2&goto :_sqr
- rem 開方循環結束
- :_endsqr
- if not !xa:~%pl%!== (
- call :_lenc !xa:~%pl%!
- if !tlc!==1 (set/a fxs=lenc-1) else (set fxs=!lenc!)
- echo 忽略位數:fxs===!fxs!rem 溢出后將被開方數忽略的位數
- )
- set/a xsl=xsl+xs-(fxs+1)/2
- rem 修正小數位數
- echo 小數位數:%xsl%rem 開方結果小數的位數
- if %fxs% gtr 0 if %xsl% lss 0 echo 非有效位數 %xsl:~1%
- if %xsl% gtr 0 (
- call :_lenc %jg%
- if !lenc! gtr %xsl% (
- set jg=!jg:~0,-%xsl%!.!jg:~-%xsl%!
- ) else (
- set/a jgl=xsl-lenc
- :ld0
- if !jgl! gtr 0 set jg=0%jg%&set/a jgl-=1&goto :ld0
- set jg=0.%jg%
- )
- )
- :ad0
- if %xsl% lss 0 set jg=%jg%0&set/a xsl+=1&goto :ad0
- if %of% equ 1 (set fh=≈) else (set fh==)
- echo 結果%fh%%jg%&ENDLOCAL&set jg=%jg%&goto :EOF
- rem End_Sqrt
- rem 計算字串長度子程序
- :_lenc
- SETLOCAL ENABLEDELAYEDEXPANSION
- set n=0&set _#=^&set stmp=%1
- :asa
- if not !stmp:~%n%,1!== set/a n+=1&goto asa
- if !stmp:~0,1!==!_#! set/a n-=2
- ENDLOCAL&set lenc=%n%
- goto :EOF
- rem End_lenc
- rem 刪除數字串兩端0的子程序,三個參數:%2 為待處理的數字串;%1=l時刪除數字串左端的0,%1=a時刪除兩端的0
- rem 其他值時刪除右端的0;%3 為變量名,保存處理完的字串。用法:Call :_dez %1=l|r|a [%2=String [%3=var]]
- :_dez
- SETLOCAL ENABLEDELAYEDEXPANSION
- set str=%2&if %3== (set var=dez) else set var=%3
- if %1==l (set ts1=0,1&set tss=1) else set ts1=-1&set tss=0,-1
- :loopz
- if !str:~%ts1%!==0 set str=!str:~%tss%!&goto :loopz
- if %1==a if !ts1!==-1 set ts1=0,1&set tss=1&goto :loopz
- ENDLOCAL&set %var%=%str%&goto :EOF
- rem End_dez
- rem ---------------------------------------------------All End
nclick="copycode($('code1'));">復制代碼
- call :_div 5 3 3
- echo 5÷3 結果 %quo%
- rem 5除以3 保留3位小數
- call :_div 16 9
- echo 16÷9 結果 %quo%
- rem 16除以9 能算幾位算幾位
- pause:goto :eof
- rem 除法計算
- :_div
- if %1== echo 請輸入被除數(參數 %%^1)&goto :EOF
- if %2== echo 請輸入除數(參數 %%^2)&goto :EOF
- SETLOCAL ENABLEDELAYEDEXPANSION
- set Maxd=2147483647&set scp=0&set ded=%1&set dvr=%2&set quo=&set psc=%3
- if %psc%== set psc=%Maxd%
- if %dvr% equ 0 ENDLOCAL&echo 錯誤,除數為零!&goto :EOF
- if %ded% equ 0 ENDLOCAL&set quo=0&goto :EOF
- if %ded%==%1 (if not %dvr%==%2 ENDLOCAL&echo 參數 %%^2 輸入錯誤或數值超限&goto :EOF)^
- else (echo 參數 %%^1 輸入錯誤或數值超限
- if not %dvr%==%2 ENDLOCAL&echo 參數 %%^2 輸入錯誤或數值超限&goto :EOF)
- :divbg
- set/a quo=ded/dvr, rdd=quo*dvr
- if %rdd% neq %ded% if %ded% leq %Maxd:~0,-1% (
- if %scp% lss %psc% set ded=%ded%0&set/a scp+=1&goto :divbg
- )
- if %quo% equ 0 ENDLOCAL&set quo=0&goto :EOF
- if %scp% neq 0 if !quo:~-%scp%!==!quo! (
- set quo=00000000%quo%&set quo=0.!quo:~-%scp%!)^
- else set quo=!quo:~0,-%scp%!.!quo:~-%scp%!
- ENDLOCAL&set quo=%quo%&goto :EOF

