我最近尝试批量编写程序,计算任何实数的平方根(而不是负数),而不使用外部命令或工具,程序基于可在此处找到的算法:
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