bash, bc modulo 不适用于 -l 标志

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27470210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 12:00:28  来源:igfitidea点击:

bash, bc modulo does not work with -l flag

bashbc

提问by Saad Attieh

So I am trying to use bcto calculate some logarithms but I also need to use it to calculate the modulus for something. Whilst making my script, I launched bcto test it.

所以我试图用它bc来计算一些对数,但我也需要用它来计算某些东西的模数。在制作我的脚本时,我开始bc测试它。

Without any flags, bc <<< "3%5"of course returns 3.

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

But with bc -l(loads math library so I can compute logarithms) any calculation of a%breturns 0where aand bcan be any number but 0.

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

What's happening?

发生了什么?

回答by gniourf_gniourf

That's because, from the manual:

那是因为,从手册中:

   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.

When you run bcwith the -lflag, scaleis set to 20. To fix this:

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

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

We first save scalein variable oldscale, then set scaleto 0to perform some arithmetic operations, and to compute a lnwe set scaleback to its old value. This will output:

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

3
.69314718055994530941

as wanted.

随心所欲。

回答by afenster

According to the bcmanual,

根据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.

So what happens is that it tries to evaluate a-(a/b)*busing the current scalesettings. The default scaleis 0 so you get the remainder. When you run bc -lyou get scale=20and the expression a-(a/b)*bevaluates to zero when using 20 fractional digits.

因此,它会尝试a-(a/b)*b使用当前scale设置进行评估。默认scale值为 0,因此您可以获得余数。当您运行时,当您使用 20 个小数位时,bc -l您会得到scale=20并且表达式的a-(a/b)*b计算结果为零。

To see how it works, try some other fractions:

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

$ bc -l
1%3
.00000000000000000001

To make a long story short, just compare three outputs:

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

Default scalewith -lenabled (20):

默认scale-l启用(20):

scale
20

3%5
0

1%4
0

Let's set scaleto 1:

让我们设置scale为 1:

scale=1

3%5
0

1%4
.2

Or to zero (default without -l):

或为零(默认没有-l):

scale=0

3%5
3

1%4
1

回答by Thor

You could define a function that works in math mode by temporarily setting scaleto zero.

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

I have bcaliased like this:

我有这样的bc别名:

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

Thus ~/.bcrcis evaluated before any other expressions, so you can define functions in ~/.bcrc. For example a modulus function:

因此~/.bcrc在任何其他表达式之前计算,因此您可以在~/.bcrc. 例如模数函数:

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

Now you can do modulo like this:

现在你可以像这样做模:

echo 'mod(5,2)' | bc

Output:

输出:

1

回答by mpiffault

man bc :

男子公元前:

If bc is invoked with the -l option, a math library is preloaded and the default scale is set to 20.

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

So maybe you should set the scale to 0 :

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

#bc
scale=0
10%3
1

回答by Unbeliever

For what it's worth, when I use bc -l, I have the following functions defined:

对于它的价值,当我使用时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))}

That should give you a proper MODfunction, while keeping your scale intact. Of course, it won't help if you NEED to use the %operator for some reason.

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

(That TRUNCfunction is quite handy too, forming the basis for many other useful functions that are outside the scope of this answer.)

(该TRUNC功能也非常方便,构成了本答案范围之外的许多其他有用功能的基础。)