批处理文件 – 批处理不能正确计算方程式

我最近尝试批量编写程序,计算任何实数的平方根(而不是负数),而不使用外部命令或工具,程序基于可在此处找到的算法:
https://en.wikipedia.org/wiki/Shifting_nth_root_algorithm

编辑:我修复了大部分问题,但仍然有一点我未检测到的问题.

请运行此“调试模式”代码:http://pastebin.com/Rd8HGYKV并测试输出数字15625和精度3.

为了使代码正确,调试代码必须显示:

- finalpart: 1
2
adder: 56
- finalpart: 44
3
adder: 25
- finalpart: 1225
4
adder: 0
Answer: 125

请帮忙!
先感谢您!

最佳答案 劳驾.如果您希望我们检查您的代码以查找错误,我无法帮助您.您的代码很大,并且没有单一的描述性注释,并且多个变量名称令人困惑,并且容易导致编辑错误.我查看了你对维基百科文章的链接,这个方法对我来说似乎很有趣,但是当我将所描述的方法与你的程序进行比较时,代码似乎不必要地复杂,所以我决定编写我自己的那个方法版本;如果这不是你要求的,我道歉.

在此程序中,精度设置为输入数字的小数位数/ 2,但非常简单的修改将允许将其设置为固定数字.我用多个数字测试了这个程序并正常工作.

@echo off
setlocal

:nextNumber
   set "number="
   set /P "number=Number:      "
   if not defined number goto :EOF
   call :SquareRoot %number% sqrt=
   echo Square root: %sqrt%
   echo/
goto nextNumber


:SquareRoot number result=
setlocal EnableDelayedExpansion

rem Separate the number in aligned blocks of 2 digits each
for /F "tokens=1,2 delims=." %%a in ("%1") do set "int=%%a" & set "frac=%%b"
set /A i=11, f=10
:nextInt
   if not defined int goto nextFrac
   set /A i-=1
   set "block[%i%]=%int:~-2%"
   set "int=%int:~0,-2%"
goto nextInt
:nextFrac
   if not defined frac goto checkLastBlock
   set /A f+=1
   set "block[%f%]=%frac:~0,2%"
   set "frac=%frac:~2%"
goto nextFrac
:checkLastBlock
if %f% gtr 10 if "!block[%f%]:~1!" equ "" set "block[%f%]=!block[%f%]!0"

rem Get square root of first block: digit between 0 and 9
set /A num=block[%i%], iP1=i+1, addZeros=0
for /L %%r in (0,1,9) do (
   set /A r2=%%r*%%r
   if !r2! leq %num% set /A sqrt=%%r, remainder=num-r2
)

rem Get square root of next blocks
for /L %%i in (%iP1%,1,%f%) do (
   set /A remainder1=remainder*10+!block[%%i]:~0,1!, remainder2=remainder*100+1!block[%%i]!-100, sqrtT2=sqrt*2
   if !sqrtT2! equ 0 (
      rem The number started with zeros: no sqrt yet
      set "sqrt="
      set /A addZeros+=1
      for /L %%r in (0,1,9) do (
         set /A r2=%%r*%%r
         if !r2! leq !remainder2! set /A nextDigit=%%r, remainder=remainder2-r2
      )
   ) else if !remainder1! lss !sqrtT2! (
      rem There is no sqrt for this block
      set /A nextDigit=0, remainder=remainder2
   ) else (
      set /A nextDigit=remainder1/sqrtT2, test=sqrtT2*10+nextDigit, this=test*nextDigit
      if !this! gtr !remainder2! (
         rem Next digit is too large: decrease it
         set /A "times=(this-remainder2)/test+1"
         for /L %%t in (1,1,!times!) do if !this! gtr !remainder2! (
            set /A nextDigit-=1, test=sqrtT2*10+nextDigit, this=test*nextDigit
         )
      )
      set /A remainder=remainder2-this
   )
   set "sqrt=!sqrt!!nextDigit!"
)

for /L %%i in (1,1,%addZeros%) do set "sqrt=0!sqrt!"
set /A point=11-i
set "sqrt=!sqrt:~0,%point%!.!sqrt:~%point%!"
endlocal & set "%2=%sqrt%"
exit /B

输出示例:

Number:      15625.000000
Square root: 125.000

Number:      625
Square root: 25.

Number:      64
Square root: 8.

Number:      9
Square root: 3.

Number:      0.25
Square root: 0.5

Number:      987654321987654321
Square root: 993807990.

Number:      1234567890123456789
Square root: 1111111106.

Number:      2.000000000000000000
Square root: 1.414213562
点赞