批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程
[批处理文件精品]批处理版照片整理器[批处理文件精品]纯批处理备份&还原驱动在线第三方下载
返回列表 发帖

[数值计算] 纯批处理版正弦函数计算器

学SICP过程中了解到的算法,今天突发奇想用批处理实现一下。纯属娱乐,无效率可言。
其实有了正弦,其它的三角函数都好说。
正弦函数计算部分由@老刘编写。
浮点数四则运算由@MHL编写,在此表示感谢。

计算原理:
    将输入的弧度诱导到[0,2*pi]之内。
    sin通过公式sin(x)=3sin(x/3)-4[sin(x/3)]^3放缩为更小的sin角来计算。
    而sin(x)与x在|x|<0.1时相差不大,故可用x替代。
    目前设定的精度要求为|x|<0.0000001时使用x替代sin(x)。

注意事项:
    放缩、累加过程通过递归实现,受批处理递归层数限制,可能溢出。
    虽然改成迭代写法可以提高效率,但是真的懒得改了(逃)。
    目前设定为保留25位小数,可自行修改。

使用方法:
    不支持表达式,请分步计算。
    计算结果会自动放入剪辑版,以供粘贴。
    内建常量:%pi%
    正弦计算:输入“sin 弧度”并回车。
    四则计算:输入“[add/multiply/divide] 数1 数2”并回车。


仅核心代码无法运行,请从下面链接中下载。
https://oldliu001.lanzous.com/iHLCmh11pcb
核心代码:纯批处理版正弦函数计算器.bat
  1. @set 保留小数位数=25
  2. @rem 保留小数位数越大越精确,但运算速度会变慢。
  3. @rem 由于批处理变量长度限制,不能超过100。
  4. @set 精度=0.0000001
  5. @rem 精度越小越精确,但运算速度会变慢。
  6. @echo off
  7. pushd "%~dp0"
  8. setlocal enabledelayedexpansion
  9. title 老刘编写——纯批处理正弦函数计算器
  10. echo 正弦函数计算部分由@老刘编写。
  11. echo 浮点数四则运算由@MHL编写,在此表示感谢。
  12. echo.
  13. echo 计算原理:
  14. echo     将输入的弧度诱导到[0,2*pi]之内。
  15. echo     sin通过公式sin^(x^)=3sin^(x/3^)-4[sin^(x/3^)]^^3放缩为更小的sin角来计算。
  16. echo     而sin^(x^)与x在^|x^|^<0.1时相差不大,故可用x替代。
  17. echo     目前设定的精度要求为^|x^|^<!精度!时使用x替代sin^(x^)。
  18. echo.
  19. echo 注意事项:
  20. echo     放缩、累加过程通过递归实现,受批处理递归层数限制,可能溢出。
  21. echo     虽然改成迭代写法可以提高效率,但是真的懒得改了(逃)。
  22. echo     目前设定为保留!保留小数位数!位小数,可自行修改。
  23. echo.
  24. echo 使用方法:
  25. echo     不支持表达式,请分步计算。
  26. echo     计算结果会自动放入剪辑版,以供粘贴。
  27. echo     内建常量:%%pi%%
  28. echo     正弦计算:输入“sin 弧度”并回车。
  29. echo     四则计算:输入“[add/multiply/divide] 数1 数2”并回车。
  30. echo.
  31. echo.
  32. echo 关闭句柄1(标准输出)。>nul 3>nul
  33. rem set /a 保留小数位数3倍=保留小数位数*3
  34. set /a 保留小数位数+=1
  35. set pi=3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
  36. call :_round pi !保留小数位数!
  37. call "multiply" !pi! 2
  38. set _2pi=!errorlevel!
  39. call :_round _2pi !保留小数位数!
  40. :loop
  41.     set /p "command=>>> ">con
  42.     call :!command!
  43.     echo.>con
  44. goto loop
  45. :add
  46. call "plus&minus" %1 %2
  47. echo 计算结果:!errorlevel! >con
  48. set /p "=!errorlevel!"<nul | clip
  49. goto :eof
  50. :divide
  51. call "divide" %1 %2 %保留小数位数%
  52. echo 计算结果:!errorlevel! >con
  53. set /p "=!errorlevel!"<nul | clip
  54. goto :eof
  55. :multiply
  56. call "multiply" %1 %2
  57. echo 计算结果:!errorlevel! >con
  58. set /p "=!errorlevel!"<nul | clip
  59. goto :eof
  60. :sin
  61. call :_sin %1
  62. echo 计算结果:!errorlevel! >con
  63. set /p "=!errorlevel!"<nul | clip
  64. goto :eof
  65. :_sin
  66. setlocal
  67. set number=%1
  68. :__sin_loop
  69. call :_isBigger !number! !_2pi!
  70. if !errorlevel! == true (
  71. call "plus&minus" !number! -!_2pi!
  72. set number=!errorlevel!
  73. goto __sin_loop
  74. )
  75. call :_isBigger !number! 0
  76. if !errorlevel! == false (
  77. rem 负弧度,转为正弧度。
  78. call :_sin !number:~1!
  79. set dest=!errorlevel!
  80. call :_isBigger !dest! 0
  81. if !errorlevel! == true (
  82. set dest=-!dest!
  83. )
  84. ) else (
  85. call :_isBigger !number! !精度!
  86. if !errorlevel! == false (
  87. rem 放缩完毕,直接返回。
  88. set dest=!number!
  89. ) else (
  90. rem 通过sin^(x^)=3sin^(x/3^)-4[sin^(x/3^)]^^3进行放缩。
  91. call "divide" !number! 3 %保留小数位数%
  92. call :_sin !errorlevel!
  93. set sinNumberDivide3=!errorlevel!
  94. call "multiply" !sinNumberDivide3! 3
  95. call :_round errorlevel %保留小数位数%
  96. set destPart1=!errorlevel!
  97. >con set sinNumberDivide3
  98. call "multiply" !sinNumberDivide3! !sinNumberDivide3!
  99. call :_round errorlevel %保留小数位数%
  100. call "multiply" !errorlevel! !sinNumberDivide3!
  101. call :_round errorlevel %保留小数位数%
  102. call "multiply" !errorlevel! 4
  103. call :_round errorlevel %保留小数位数%
  104. set destPart2=!errorlevel!
  105. >con set destPart2
  106. rem destPart2必定是正数。
  107. call "plus&minus" !destPart1! -!destPart2!
  108. set dest=!errorlevel!
  109. call :_round dest %保留小数位数%
  110. )
  111. )
  112. for %%a in (!dest!) do endlocal&set errorlevel=%%a
  113. goto :eof
  114. :_isBigger number1 number2
  115. rem 若数1比数2大(或等),返回true,否则返回false。
  116. setlocal
  117. set number2=%2
  118. if "!number2:~,1!" == "-" (
  119. set "number2=+!number2:~1!"
  120. ) else (
  121. set "number2=-!number2!"
  122. )
  123. rem echo call "plus&minus" %1 !number2! >con
  124. call "plus&minus" %1 !number2!
  125. if "!errorlevel:~,1!" == "-" (
  126. set dest=false
  127. ) else (
  128. set dest=true
  129. )
  130. for %%a in (!dest!) do endlocal&set errorlevel=%%a
  131. rem echo 计算结果:!errorlevel! >con
  132. rem set /p "=!errorlevel!"<nul | clip
  133. goto :eof
  134. :_round 四舍五入函数(提高精度用) 变量 保留小数位数-1
  135. setlocal
  136. rem 备份%1,使其支持处理errorlevel。
  137. set number=!%1!
  138. rem 若无小数部分,直接返回。
  139. if "!number!" equ "!number:.=!" goto :eof
  140. rem 若位数比保留位数少,直接返回。
  141. set demicalPart=!number:*.=!
  142. set /a __round_tmp=%2-1
  143. for %%a in (!__round_tmp!) do (
  144. if "!demicalPart:~%%a,1!" equ "" goto :eof
  145. )
  146. rem 从最后一位向前四舍五入到指定的位数。
  147. set carry=0
  148. :__round_loop
  149. set /a lastNum=!demicalPart:~-1!+carry
  150. set carry=0
  151. if !lastNum! geq 5 set carry=1
  152. :__round_jumpin
  153. if "!demicalPart:~%2,1!" equ "" (
  154. set demicalPart=!demicalPart:~,-1!
  155. set /a lastNum=!demicalPart:~-1!+carry
  156. set carry=0
  157. goto __round_loop2
  158. )
  159. set demicalPart=!demicalPart:~,-1!
  160. goto __round_loop
  161. rem 若出现9+1,则继续进位。
  162. :__round_loop2
  163. if !lastNum! equ 10 (
  164. set demicalPart=!demicalPart:~,-1!
  165. set /a lastNum=!demicalPart:~-1!+1
  166. if "!demicalPart!" neq "" (
  167. goto __round_loop2
  168. ) else (
  169. set demicalPart=0
  170. set carry=1
  171. )
  172. ) else (
  173. set demicalPart=!demicalPart:~,-1!!lastNum!
  174. )
  175. call "plus&minus" !number! !carry!
  176. for /f "tokens=1,3 delims=. " %%a in ("!errorlevel! !demicalPart!") do endlocal&set %1=%%a.%%b
  177. rem echo 计算结果:!%1! >con
  178. rem set /p "=!%1!"<nul | clip
  179. goto :eof
复制代码

返回列表