整数

整数

如果比例不是零,则带有百分比的计算(例如 3%2 和 46%4)往往会输出 0。对于非 0 比例,算法是如何设计的?

bc
scale=10
print 4%3   // output 0

答案1

命令手册关于 BC 如何计算模数,如下所述:

表达式的结果为“余数”,计算方式如下。要计算 a%b,首先一个/b计算成比例数字。该结果用于计算a-(a/b)*b到 scale+scale(b) 和 scale(a) 中最大值的比例。如果比例设置为零并且两个表达式都是整数,则该表达式就是整数余数函数。


编辑: 我查看了 GNU BC 的源代码,发现 mod 运算符扩展了除法运算符。换句话说,模数是作为除法的副产品计算的。它依赖于整数除法来计算模数。scale但是,当设置时,不会发生整数除法。

在 BC 尝试一下:

bc
scale = 0
print 5/2

scale = 5
print 5/2

你应该得到:

2        << Integer Division
2.50000  << NOT integer division!

现在让我们按照 BC 的方式代入这些数字。手册上说它使用a-(a/b)*b进行计算。让我们代入两个结果,一个是整数除法的结果,另一个是scale除以 0 以外的结果。

a - ( a/b ) * b
5 - ( 2   ) * 2  = 1  << CORRECT!
5 - ( 2.5 ) * 2  = 0  << VERY WRONG!

不进行整数除法:

a - ( a/b ) * b == a - (  a  ) == 0

这就是为什么必须将比例设置为 0 才能使模数正常工作的原因。
问题似乎源于 BC 的设计以及它如何处理带有“比例”的数字。为了使模数正常工作我们需要整数除法

其他很多更先进的工具它们是免费和开源的,用于此目的,我建议你使用它们。

答案2

user272970 的回答很棒。下面是一些调整:

define int(x) { auto oldscale; oldscale=scale; scale=0; x=x/1; scale=oldscale; return( x ); }
define fmod(x,y) { auto oldscale; oldscale=scale; scale=1000; x = x - y * int(x/y); scale=oldscale; return( x ); }

这(使用auto oldscale)使 成为oldscale函数的本地变量。如果没有它,则fmod() 中oldscale的设置将覆盖试图保存在 中的,从而使其设置为 1000,而不是调用 之前的任何值。int()oldscalefmod()scalefmod()

我将这些函数添加到~/.bcrc并将BC_ENV_ARGS环境变量设置为~/.bcrc。每次运行 bc 时都会加载这些函数。所以现在我可以fmod(x,y)在 bc 中随时运行,而不必每次都手动定义这些函数。

scale在大多数情况下,1000 ps可能有点过头了

答案3

我用这种方法解决了:

整数

定义 int(x) { oldscale=scale; scale=0; x=x/1; scale=oldscale; 返回(x); }

模数

定义 mod(x,y) { oldscale=scale; scale=1000; x = x - y * int(x/y); scale=oldscale; 返回(x); }

高血压

答案4

正如其他答案所说,它是定义a%b为的结果(a-(a/b)*b),在当前 处进行评估scale。这意味着如果您希望它充当整数模数,则需要将其与 一起使用scale=0

然而,我不同意它是“错误的”。它是一种潜在的有用工具,特别是用于评估错误。

scale=5
1/3
> .33333
1%3
> .00001

7/13如果我们将其表示为 4 位小数,我们会失去什么.5384

scale=4
7/13
> .5384
7%13
> .0008

显然0.0008/13

最后,因为它不坚持使用整数,所以它可以用于提取小数的一部分。

scale=1
123.456/1
> 123.4
123.456%1
> .056

相关内容