[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
开方,即将数字的2进制位截取一半..
使用移位算法,复杂度会大幅下降。

比如 4*4 = 16 , 2^2=4, 2^4=16; 把4位二进制数变成2位即可。
又如,2^4=16, 16*16=256, 2^(4*2)=256 。
反过来开方 256 就是把2^(8/2)。
1

评分人数

    • zm900612: 另辟蹊径,赞!PB + 6 技术 + 1

TOP

本帖最后由 caruko 于 2011-5-26 03:59 编辑

任何整数都是 1 2 4 8 ... 这些数字之和
7 = 2^2 + 2^1 +2^0 ,即 set /a "(1<<2)+(1<<1)+(1<<0)"
(2^2 + 2^1 +2^0)*(2^2 + 2^1 +2^0) = (2^4 + 2^3 + 2^2) + (2^3 + 2^2 + 2^1) + (2^2 + 2^1 + 2^0)

就相当于嵌套的 for %%i in (2 1 0) do for %%j in (2 1 0) do set /a v+=1"<<"(%%i+%%j)


好吧,完全平方的多项式分解很麻烦。

算法如下
实际上,得出 1<<5 小于  49 小于 1<<6,可以得出 49的根为 x=(5/2) ,即1<<2位, 3位2进制数。
for /l %%i in (x,-1,0) do (
               set /a v+=1<<%%i
               if v*v  gtr 49 set /a v-=1<<%%i
               if v*v equ 49 ( break & echo v )
)
如果仍然未出结果,就涉及小数。
那么把 v 左移 2位,把 49 左移4位,继续计算。在未溢出的情况下,算完之后右移2位,就能得到 2位小数的根了。

TOP

本帖最后由 caruko 于 2011-5-26 14:37 编辑

按照上面的算法,我也放一个开方代码。
32位限制,精确度在5位左右。
修改了一个数值接近MAX时,导致变量k为空的,无法输出结果的小错误。
  1. @echo off&SETLOCAL ENABLEDELAYEDEXPANSION
  2. ::最大被开方数,2147483647  < 2^31
  3. ::最大开方数, < 2^16
  4. ::每次都将输入数值增加10^2n次,尽量增加到接近MAX的数,
  5. ::检测输入
  6. :loop
  7. 2>nul set /a 1/%1 &&(set "input=%1")||(set /p input=请输入被开方数字:)
  8. 2>nul set /a 1/input ||goto :loop
  9. call :kf !input!
  10. goto :eof
  11. :kf
  12. setlocal
  13. ::在溢出范围内提高位数,增加精确度。
  14. set /p=被开方数:!input!,结果:<nul
  15. set /a input=%1,cs=1
  16. for /l %%i in (1,1,8) do (
  17.     set /a cs*=10
  18.     if "!cs:00=!"=="1" (
  19.         set /a x=input*cs,y=x/cs
  20.         if !input! equ !y! set /a tp=x,k=%%i/2
  21. ))
  22. if "!tp!"=="" (
  23.   set /a k=0
  24.   ) else (
  25.   set /a input=tp
  26. )
  27. :: 检测被开方数2进制的位数。
  28. set "ofset="
  29. for /l %%i in (0,1,31) do (
  30.     set /a v=1"<<"%%i
  31.     if %%i equ 31 set /a v=v+1&set v=!v:-=!
  32.     if not defined ofset if !v! gtr !input! set /a ofset=%%i-1
  33. )
  34. if not defined ofset (
  35.     echo,输入数字超标!
  36.     exit /b -1
  37. )
  38. set /a kofset=ofset/2,v=0
  39. ::求被开方数,整数部分。
  40. for /l %%i in (!kofset!,-1,0) do (
  41.     set /a v+=1"<<"%%i,flag=v*v
  42.     if !flag! gtr !input! set /a v-=1"<<"%%i
  43. )
  44. for /f %%a in ("!k!") do set ecode=!v:~0,-%%a!.!v:~-%%a!
  45. if !k! equ 0 set ecode=!v!.0
  46. echo,!ecode!
  47. endlocal
复制代码
1

评分人数

TOP

返回列表