F#: integer (%) integer - 是如何计算的?

F#: integer (%) integer - Is Calculated How?

所以在我的课本中有一个使用 f#

的递归函数示例
let rec gcd = function
| (0,n) -> n
| (m,n) -> gcd(n % m,m);;

有了这个函数,我的教科书通过执行给出了例子:

gcd(36,116);;

并且由于 m = 36 而不是 0 那么它当然适用于第二个子句,如下所示:

gcd(116 % 36,36)
gcd(8,36)
gcd(36 % 8,8)
gcd(4,8)
gcd(8 % 4,4)
gcd(0,4) 
and now hits the first clause stating this entire thing is = 4.

我不明白的是这个 (%) 百分比 sign/operator 或在这方面的任何称呼。例如,我不明白如何

116 % 36 = 8

我已经在脑海里转了很多遍了,我想不通这怎么变成8?

我知道对于那些知道这个的人来说这可能是一个愚蠢的问题,但我同样非常感谢你的帮助。

因为

116 / 36 = 3
116 - (3*36) = 8

%modulo 的一个有问题的版本,它是整数除法的余数。

在正数中,可以把%看做除法的余数。参见示例 Wikipedia on Euclidean Divison。考虑 9 % 4:4 适合 9 两次。但是四乘以二只有八。这样一来就有余数了。

如果有负操作数,%有效地忽略符号来计算余数,然后使用被除数的符号作为结果的符号。这对应于四舍五入为零的整数除法的余数,即 -2 / 3 = 0.

这是除法和余数的数学上不寻常的定义,具有一些不良性质。通常,在计算 modulo n 时,在输入上添加或减去 n 没有任何影响。此运算符并非如此:2 % 3 不等于 (2 - 3) % 3.

我通常定义以下内容以在存在负操作数时获得有用的余数:

/// Euclidean remainder, the proper modulo operation
let inline (%!) a b = (a % b + b) % b

到目前为止,这个运算符对我遇到的所有需要​​取模的情况都是有效的,而原始 % 一再不是。例如:

  • 从单个索引填充行和列时,可以计算rowNumber = index / nColscolNumber = index % nCols。但是如果indexcolNumber可以为负数,这个映射就失效了,而欧氏除法和余数仍然有效。

  • 如果你想将一个角度归一化为 (0, 2pi),angle %! (2. * System.Math.PI) 可以完成这项工作,而 "normal" % 可能会让你头疼.

基本上,称为 modulo operator 的 % 运算符会将一个数字除以其他数字,如果不能再除以剩余部分。通常,如果您想通过在 f#

中执行类似的操作来查看数字是偶数还是奇数,您第一次使用它来理解它
let firstUsageModulo = 55 %2 =0 // false because leaves 1 not 0

当它第一次离开8时意味着它把你116除以36最接近的整数是8给。

只是为了帮助您将来解决类似的问题:在 Xamarin Studio 和 Visual Studio 等 IDE 中,如果您将鼠标光标悬停在诸如 % 之类的运算符上,您应该会得到一个工具提示,因此:

Module operator tool tip

即使您不直接理解工具提示,它也会给您一些帮助 google。