【发布时间】:2015-02-12 17:34:39
【问题描述】:
所以我尝试使用bc 来计算一些对数,但我还需要使用它来计算某些东西的模数。在编写脚本时,我启动了bc 来测试它。
没有任何标志,bc <<< "3%5" 当然会返回3。
但是使用bc -l(加载数学库以便我可以计算对数)a%b 的任何计算都会返回0,其中a 和b 可以是除0 之外的任何数字。
发生了什么事?
【问题讨论】:
所以我尝试使用bc 来计算一些对数,但我还需要使用它来计算某些东西的模数。在编写脚本时,我启动了bc 来测试它。
没有任何标志,bc <<< "3%5" 当然会返回3。
但是使用bc -l(加载数学库以便我可以计算对数)a%b 的任何计算都会返回0,其中a 和b 可以是除0 之外的任何数字。
发生了什么事?
【问题讨论】:
那是因为,根据手册:
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
随心所欲。
【讨论】:
根据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
【讨论】:
您可以通过将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
【讨论】:
人公元前:
如果使用 -l 选项调用 bc,则会预加载数学库并 默认比例设置为 20。
所以也许你应该将比例设置为 0:
#bc
scale=0
10%3
1
【讨论】:
不管怎样,当我使用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 函数也非常方便,构成了此答案范围之外的许多其他有用函数的基础。)
【讨论】: