【问题标题】:Floating point division in a batch file批处理文件中的浮点除法
【发布时间】:2009-10-01 13:16:11
【问题描述】:

我需要在 dos 批处理中进行浮点除法。

我没有找到办法。像这样:

SET /A Res=10/3

返回一个整数。

有可能吗?

【问题讨论】:

  • 你到底为什么需要这样做?您是否考虑过 VBScript 或其他脚本引擎?
  • 我一直在研究一个批处理 bignum 库。不过,还没有完成。
  • 如果您仍然对纯批处理感兴趣。 dostips.com/forum/viewtopic.php?t=3854

标签: batch-file


【解决方案1】:

我知道这是一个很老的话题,但是在之前的所有答案中都找不到简单的 Batch 方法,所以在这里发布一个非常简单易用的纯 Batch 解决方案。

在 Batch 中使用定点算术执行操作很简单。 “定点”意味着您必须提前设置小数位数并在整个操作过程中保持不变。两个定点数之间的加减运算是直接执行的。乘法和除法运算需要一个辅助变量,我们可以称之为“一”,其值为 1 和正确的小数位数(如“0”位)。相乘后,乘积除以“一”;在除法之前,将被除数乘以“一”。这里是:

@echo off
setlocal EnableDelayedExpansion

set decimals=2

set /A one=1, decimalsP1=decimals+1
for /L %%i in (1,1,%decimals%) do set "one=!one!0"

:getNumber
set /P "numA=Enter a number with %decimals% decimals: "
if "!numA:~-%decimalsP1%,1!" equ "." goto numOK
echo The number must have a point and %decimals% decimals
goto getNumber

:numOK
set numB=2.54

set "fpA=%numA:.=%"
set "fpB=%numB:.=%"

set /A add=fpA+fpB, sub=fpA-fpB, mul=fpA*fpB/one, div=fpA*one/fpB

echo %numA% + %numB% = !add:~0,-%decimals%!.!add:~-%decimals%!
echo %numA% - %numB% = !sub:~0,-%decimals%!.!sub:~-%decimals%!
echo %numA% * %numB% = !mul:~0,-%decimals%!.!mul:~-%decimals%!
echo %numA% / %numB% = !div:~0,-%decimals%!.!div:~-%decimals%!

例如:

Enter a number with 2 decimals: 3.76
3.76 + 2.54 = 6.30
3.76 - 2.54 = 1.22
3.76 * 2.54 = 9.55
3.76 / 2.54 = 1.48

【讨论】:

  • 非常好!我不知道这不是公认的答案,因为它很简单;将一个整数乘以 10000 得到 4 个小数,依此类推。
  • 这段代码的问题是当你输入0.17numA 时结果会出错,因为前导零会将其解释为八进制数,
【解决方案2】:

这样的批处理文件不支持浮点运算。但是,this article 建议使用外部脚本文件进行计算的解决方法。脚本文件应该使用某种eval 函数来评估作为参数传递的表达式并返回结果。这是执行此操作的示例 VBScript 文件 (eval.vbs):

WScript.Echo Eval(WScript.Arguments(0))

您可以从批处理文件中调用此外部脚本,指定要计算的表达式并返回结果。例如:

@echo off
for /f %%n in ('cscript //nologo eval.vbs "10/3"') do (
  set res=%%n
)
echo %res%

当然,你会得到一个字符串的结果,但总比没有好,你可以将得到的结果作为另一个表达式的一部分传递给 eval 脚本。

【讨论】:

  • 你不能将结果传递给另一个 eval 脚本——至少在一般情况下是这样。这些数字针对您当前的语言环境进行了格式化。就我而言,这意味着逗号, 用作小数点。如果我将结果再次放入脚本中,这会导致语法错误。
【解决方案3】:

根据this reference,DOS批处理语言中没有浮点类型:

虽然在 DOS 批处理编程语言中确实存在变量,但它们非常有限。没有整数、指针或浮点变量类型,只有字符串。

如果不实施您自己的除法方案来明确计算余数,我认为您要尝试做的事情是不可能的。

【讨论】:

  • 即使它们只是字符串,您也可以使用 set /a 进行有符号 32 位整数运算。
【解决方案4】:

我最近遇到了这个批处理文件来计算 Pi 的近似值。 有一个DivideByInteger 标签可能对您有用:Stupid-Coding-Tricks-A-Batch-of-Pi

它使用一组MaxQuadIndex 变量,每个变量都包含一个四位数(四位),以便存储整个结果。该代码允许除以 1 到 10000 之间的整数,包括 1 到 10000。

:DivideByInteger
    if defined PiDebug echo.DivideByInteger %1 %2
    set /a DBI_Carry = 0
    for /L %%i in (!MaxQuadIndex!, -1, 0) do (
        set /a DBI_Digit = DBI_Carry*10000 + %1_%%i
        set /a DBI_Carry = DBI_Digit %% %2
        set /a %1_%%i = DBI_Digit / %2
    )
    goto :EOF

Print 标签也可用...

【讨论】:

    【解决方案5】:

    试试这个

    SETLOCAL EnableExtensions EnableDelayedExpansion
    call :calc_ 1 (99-(100*5/100^)^)
    echo !calc_v!
    goto :EOF
    :calc_
    set scale_=1
    set calc_v=
    for /l %%i in (1,1,%1) do set /a scale_*=10
    set /a "calc_v=!scale_!*%2"
    set /a calc_v1=!calc_v!/!scale_!
    set /a calc_v2=!calc_v!-!calc_v1!*!scale_!
    set calc_v=!calc_v1!.!calc_v2!
    goto :EOF
    

    改变一下

    调用 :calc_ 小数点方程

    在示例中

    小数点为 1

    等式是 (99-(100*5/100^)^) ;请确保您使用 () 时在 ) 之前插入 ^,如 ^)

    答案是 94.0

    如果小数点为 2

    等式是 22/7 ;π pi

    答案是 3.14

    【讨论】:

      【解决方案6】:

      我写了一个纯批处理文件专门做除法。它采用您输入的第一个数字,然后将其除以第二个数字,并以您指定的小数点数显示结果。

      Echo off
      cls
      if NOT "%3" == "" (
      set n1=%1
      set n2=%2
      set max=%3
      goto :begin
      )
      
      set counter=2
      set n1=1
      set n2=1
      set ans=
      :start
      Echo.
      Echo. 1 / 2
      Echo.
      Set /p N1= 1?
      set /p N2= 2?
      Set /p Max= Out how many Decimal Points?
      :begin
      set /a TmpAns=%N1%/%N2%
      set ans=%TmpAns%.
      :: Echo.%ans%.>Answer.txt
      <nul set /p "=%Tmpans%."
      set /a TmpSub=%N2%*%TmpAns%
      set /a N1=%N1%-%TmpSub%
      set N1=%N1%0
      If NOT "%n1%" == "00" (
      if %n1% LSS %N2% (
      set N1=%N1%0
      set ans=%ans%0
      )
      ) else (
      Goto :Finished
      )
      set count=0
      
      :loop
      If "%count%" == "%max%" (
      Goto :Finished
      )
      
      set /a TmpAns=%N1%/%N2%
      set ans=%ans%%TmpAns%
      <nul set /p "=%Tmpans%"
      set /a TmpSub=%N2%*%TmpAns%
      set /a N1=%N1%-%TmpSub%
      set N1=%N1%0
      If NOT "%n1%" == "00" (
      if %n1% LSS %N2% (
      set N1=%N1%0
      set ans=%ans%0
      )
      ) else (
      Goto :Finished
      )
      set /a count=%count%+1
      goto :loop
      
      :finished
      cls
      Echo.
      Echo.
      Echo.The Number
      Echo.%ans%
      Echo.
      Echo.
      set n1=1
      set n2=1
      pause
      goto :eof
      
      :eof
      

      答案放入变量 %Ans%。也可以带参数调用。 (“Divide.bat 50 27 5”会给你 50/27 出 5 个小数点。)

      【讨论】:

        【解决方案7】:

        由于现在几乎所有机器上都存在 PowerShell,我会让 PowerShell 进行数学运算并将结果返回给批处理。

        示例

        set divident=10
        set divisor=3
        for /f "delims=" %%a in ('powershell -Command %divident%/%divisor%') do set result=%%a
        @echo %result%
        

        解释

        输入变量:使用集合变量定义除数和除数。

        调用 powershell 并将结果分配给批处理变量:for /f "delims=" %%a in ('powershell -Command ...) do set result=%%a(您可以也可以在这里查看:How to put a single PowerShell output string into a cmd variable?)

        请注意,上述代码仅适用于整数输入变量。 为了支持浮点输入变量,我们需要将变量作为引号 ("%variable%") 内的字符串发送,并将 PowerShell 中的字符串转换回 Double,否则批处理会将逗号解释为分隔符,而 PowerShell 无法解释数字。

        示例

        set divident=10,5
        set divisor=3,4
        for /f "delims=" %%a in ('powershell -Command [convert]::ToDouble^(\"%divident%\"^)
                                                /[convert]::ToDouble^(\"%divisor%\"^)') do set result=%%a
        @echo %result%
        

        解释

        请注意,在 PowerShell 中,您可以像 [convert]::ToDouble("10,5")/[convert]::ToDouble("3,5") 那样执行此操作。但是在批处理中,我们需要使用反斜杠转义引号,并且我们还需要在引号部分之前和之后添加一个“^”符号:[convert]::ToDouble^("%divident%"^)/[ convert]::ToDouble^("%divisor%"^)

        【讨论】:

          【解决方案8】:

          如果您在 Windows(而不是 DOS)上的命令 shell 中运行,则可以使用 VBScript 为您计算复杂的表达式,包括浮点数学。

          我编写了一个小型帮助库,您可以调用它来执行此操作。

          EvalBat Library on GitHub

          【讨论】:

            猜你喜欢
            • 2020-12-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-07-17
            • 1970-01-01
            相关资源
            最近更新 更多