【问题标题】:bash, bc modulo does not work with -l flagbash,bc 模不适用于 -l 标志
【发布时间】:2015-02-12 17:34:39
【问题描述】:

所以我尝试使用bc 来计算一些对数,但我还需要使用它来计算某些东西的模数。在编写脚本时,我启动了bc 来测试它。

没有任何标志,bc <<< "3%5" 当然会返回3

但是使用bc -l(加载数学库以便我可以计算对数)a%b 的任何计算都会返回0,其中ab 可以是除0 之外的任何数字。

发生了什么事?

【问题讨论】:

    标签: bash bc


    【解决方案1】:

    那是因为,根据手册:

       expr % expr
              The result of the expression is the "remainder" and it  is  com‐
              puted  in  the following way.  To compute a%b, first a/b is com‐
              puted to scale digits.  That result is used to compute a-(a/b)*b
              to  the scale of the maximum of scale+scale(b) and scale(a).  If
              scale is set to zero and  both  expressions  are  integers  this
              expression is the integer remainder function.
    

    当您使用-l 标志运行bc 时,scale 设置为20。要解决这个问题:

    bc -l <<< "oldscale=scale; scale=0; 3%5; scale=oldscale; l(2)"
    

    我们首先将scale 保存在变量oldscale 中,然后将scale 设置为0 以执行一些算术运算,并计算ln 我们将scale 设置回其旧值。这将输出:

    3
    .69314718055994530941
    

    随心所欲。

    【讨论】:

      【解决方案2】:

      根据bc手册,

         expr % expr
                The result of the expression is the "remainder" and it is computed 
                in the following way.  To compute a%b, first a/b is computed to
                scale digits.   That  result  is used to compute a-(a/b)*b to the 
                scale of the maximum of scale+scale(b) and scale(a).  If scale is
                set to zero and both expressions are integers this expression is 
                the integer remainder function.
      

      因此,它会尝试使用当前的 scale 设置来评估 a-(a/b)*b。默认的scale 是 0,所以你得到余数。当您运行 bc -l 时,您会得到 scale=20,而表达式 a-(a/b)*b 在使用 20 位小数时计算为零。

      要查看它是如何工作的,请尝试其他分数:

      $ bc -l
      1%3
      .00000000000000000001
      

      长话短说,只需比较三个输出:

      默认scale 启用-l (20):

      scale
      20
      
      3%5
      0
      
      1%4
      0
      

      让我们将scale 设置为 1:

      scale=1
      
      3%5
      0
      
      1%4
      .2
      

      或归零(默认不带-l):

      scale=0
      
      3%5
      3
      
      1%4
      1
      

      【讨论】:

        【解决方案3】:

        您可以通过将scale 临时设置为零来定义一个在数学模式下工作的函数。

        我有 bc 这样的别名:

        alias bc='bc -l ~/.bcrc'
        

        因此~/.bcrc 在任何其他表达式之前被评估,因此您可以在~/.bcrc 中定义函数。例如模函数:

        define mod(x,y) { 
          tmp   = scale
          scale = 0
          ret   = x%y
          scale = tmp
          return ret
        }
        

        现在你可以像这样做模数:

        echo 'mod(5,2)' | bc
        

        输出:

        1
        

        【讨论】:

          【解决方案4】:

          人公元前:

          如果使用 -l 选项调用 bc,则会预加载数学库并 默认比例设置为 20。

          所以也许你应该将比例设置为 0:

          #bc
          scale=0
          10%3
          1
          

          【讨论】:

            【解决方案5】:

            不管怎样,当我使用bc -l 时,我定义了以下函数:

            define trunc(x)   {auto s; s=scale; scale=0; x=x/1; scale=s; return x}
            define mod(x,y)   {return x-(y*trunc(x/y))}
            

            这应该给你一个适当的MOD 函数,同时保持你的规模完好无损。当然,如果您出于某种原因需要使用 % 运算符,这将无济于事。

            TRUNC 函数也非常方便,构成了此答案范围之外的许多其他有用函数的基础。)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2022-01-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-10-11
              • 1970-01-01
              • 2015-11-29
              相关资源
              最近更新 更多