『楼 主』:
[原创]批处理计算N次方根
因为批处理支持的数字大小有限,并且本身不支持小数,所以计算得到的精确度可能不是太高。
这是一个牛顿迭代法的实现,相关内容请自己去看。
两个“函数”中有几行注释掉的 echo 语句,打开的话可以看见计算过程。
NewtonIteration.bat ver1.0
@echo off
:: 由于命令行只能使用整数,且最大位 32 位
:: 因此这两个方法能计算的数的绝对值最大值不超过 2147483648
:: 同时计算比较高的次数时,误差会比较大
:: 计算的结果是精确值在与结果相同的精度下截取的前几位
call :NewtonIterationFloat 170.36 2 pfg
call :NewtonIterationInteger 987654321 7 root7
echo === 测试 170.36 的平方根是 %pfg% ===
echo === 测试 987654321 的七次方根的整数部分是 %root7% ===
pause
goto :EOF
REM (C)2010 qinchun36 牛顿迭代法求 N 次方根
REM 求一个浮点数 %1 的 %2 次方根的近似值
REM 并将结果赋值到变量名 %3 中(没有则直接显示结果)
REM 需要调用 :NewtonIterationInteger
:NewtonIterationFloat
REM 系统能接受的最大数值及其长度
set /a _$MAX_NUMBER=2147483648
set /a _$MAX_LENGTH=10
set _$number=%1
set /a _$exp=%2
set "_$num=%_$number:.=%0000000000"
for /f "tokens=1,2" %%a in ("%_$number:.= %") do set /a "_$nD=%%a,_$nF=%%b" 2>nul
set /a _$lD=0,_$lF=0
for /l %%a in (0,1,%_$MAX_LENGTH%) do call set /a "_$temp=%%_$nD:~%%a,1%%" 2>nul && set /a _$lD+=1
for /l %%a in (0,1,%_$MAX_LENGTH%) do call set /a "_$temp=%%_$nF:~%%a,1%%" 2>nul && set /a _$lF+=1
set /a _$lR=_$MAX_LENGTH-_$lD,_$lM=_$lR/_$exp,_$lA=_$lD+_$lM*_$exp
call set /a _$num=%%_$num:~0,%_$lA%%%
if %_$num% geq %_$MAX_NUMBER% (
set /a _$lM-=1,_$lA=_$lD+_$lM*_$exp
set "_$num=%_$number:.=%"
call set /a _$num=%%_$num:~0,%_$lA%%%
)
if %_$lM% equ 0 (
call set _$number2=%%_$num:~0,%_$lD%%%
) else (
call set _$number2=%%_$num:~0,%_$lD%%%.%%_$num:~%_$lD%%%
)
::echo 数字 %_$number% 的可计算值为 %_$number2%
call :NewtonIterationInteger %_$num% %_$exp% _$rs2
if %_$lM% equ 0 (
call set "_$rs=%_$rs2%"
) else (
call set "_$rs=%%_$rs2:~0,-%_$lM%%%.%%_$rs2:~-%_$lM%%%"
)
::echo 将 %_$rs2% 的小数点向左移 %_$lM% 位得到结果 %_$rs%
set "%3=%_$rs%" 2>nul||echo.%_$rs%
goto>nul 2>&1
REM === End of :NewtonIterationFloat ===
REM (C)2010 qinchun36 牛顿迭代法求 N 次方根
REM 求一个整数 %1 的 %2 次方根的整数部分
REM 并将结果赋值到变量名 %3 中(没有则直接显示结果)
:NewtonIterationInteger
set /a $x=%1,$n=%2,$n1=$n-1,$$=0,$c=0
set "$y="
for /l %%i in (0,%$n%,10) do call set "$y=%%$y%%%%$x:~%%i,1%%"
::echo 整数 %$x% 的 %$n% 次方根预测值 %$y%
:_NewtonIterationInteger_loop
if %$y% neq %$$% (
set /a $c+=1,$$=$y,$y=$x
for /l %%i in (1,1,%$n1%) do set /a $y/=$$
set /a $y+=$n1*$$,$y/=$n
goto :_NewtonIterationInteger_loop
)
::echo 用牛顿迭代法迭代 %$c% 次后得到近似值 %$$%
set "%3=%$$%" 2>nul||echo.%$$%
goto>nul 2>&1
REM === End of :NewtonIterationInteger ===
|