找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 14366|回复: 0

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

[复制链接]
发表于 2020-9-29 16:34:22 | 显示全部楼层 |阅读模式
学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.                        
  98.                         >con set sinNumberDivide3
  99.                         call "multiply" !sinNumberDivide3! !sinNumberDivide3!
  100.                         call :_round errorlevel %保留小数位数%
  101.                         call "multiply" !errorlevel! !sinNumberDivide3!
  102.                         call :_round errorlevel %保留小数位数%
  103.                         call "multiply" !errorlevel! 4
  104.                         call :_round errorlevel %保留小数位数%
  105.                         set destPart2=!errorlevel!
  106.                         >con set destPart2
  107.                        
  108.                         rem destPart2必定是正数。
  109.                         call "plus&minus" !destPart1! -!destPart2!
  110.                         set dest=!errorlevel!
  111.                         call :_round dest %保留小数位数%
  112.                 )
  113.         )
  114.         for %%a in (!dest!) do endlocal&set errorlevel=%%a
  115. goto :eof

  116. :_isBigger number1 number2
  117.         rem 若数1比数2大(或等),返回true,否则返回false。
  118.         setlocal
  119.         set number2=%2
  120.         if "!number2:~,1!" == "-" (
  121.                 set "number2=+!number2:~1!"
  122.         ) else (
  123.                 set "number2=-!number2!"
  124.         )
  125.         rem echo call "plus&minus" %1 !number2! >con
  126.         call "plus&minus" %1 !number2!
  127.         if "!errorlevel:~,1!" == "-" (
  128.                 set dest=false
  129.         ) else (
  130.                 set dest=true
  131.         )
  132.         for %%a in (!dest!) do endlocal&set errorlevel=%%a
  133.         rem echo 计算结果:!errorlevel! >con
  134.         rem set /p "=!errorlevel!"<nul | clip
  135. goto :eof

  136. :_round 四舍五入函数(提高精度用) 变量 保留小数位数-1
  137.         setlocal
  138.        
  139.         rem 备份%1,使其支持处理errorlevel。
  140.         set number=!%1!
  141.        
  142.         rem 若无小数部分,直接返回。
  143.         if "!number!" equ "!number:.=!" goto :eof
  144.        
  145.         rem 若位数比保留位数少,直接返回。
  146.         set demicalPart=!number:*.=!
  147.         set /a __round_tmp=%2-1
  148.         for %%a in (!__round_tmp!) do (
  149.                 if "!demicalPart:~%%a,1!" equ "" goto :eof
  150.         )
  151.        
  152.         rem 从最后一位向前四舍五入到指定的位数。
  153.         set carry=0
  154.         :__round_loop
  155.         set /a lastNum=!demicalPart:~-1!+carry
  156.         set carry=0
  157.         if !lastNum! geq 5 set carry=1
  158.         :__round_jumpin
  159.         if "!demicalPart:~%2,1!" equ "" (
  160.                 set demicalPart=!demicalPart:~,-1!
  161.                 set /a lastNum=!demicalPart:~-1!+carry
  162.                 set carry=0
  163.                 goto __round_loop2
  164.         )
  165.         set demicalPart=!demicalPart:~,-1!
  166.         goto __round_loop
  167.        
  168.        
  169.         rem 若出现9+1,则继续进位。
  170.         :__round_loop2
  171.         if !lastNum! equ 10 (
  172.                 set demicalPart=!demicalPart:~,-1!
  173.                 set /a lastNum=!demicalPart:~-1!+1
  174.                 if "!demicalPart!" neq "" (
  175.                         goto __round_loop2
  176.                 ) else (
  177.                         set demicalPart=0
  178.                         set carry=1
  179.                 )
  180.         ) else (
  181.                 set demicalPart=!demicalPart:~,-1!!lastNum!
  182.         )
  183.         call "plus&minus" !number! !carry!
  184.         for /f "tokens=1,3 delims=. " %%a in ("!errorlevel! !demicalPart!") do endlocal&set %1=%%a.%%b
  185.        
  186.         rem echo 计算结果:!%1! >con
  187.         rem set /p "=!%1!"<nul | clip
  188. goto :eof
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-16 20:20 , Processed in 0.017150 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表