[英]Scala tail recursive method has an divide and remainder error
我目前正在通过在 Scala 中编写尾递归来计算两个自然数的二项式系数。 但是我的代码在除数方面有问题,像我一样用 k 整数除法,因为这会给你一个非零的余数,因此会引入舍入错误。 那么谁能帮我弄清楚,如何解决?
def binom(n: Int, k: Int): Int = {
require(0 <= k && k <= n)
def binomtail(n: Int, k: Int, ac: Int): Int = {
if (n == k || k == 0) ac
else binomtail(n - 1, k - 1, (n*ac)/k)
}
binomtail(n,k,1)
}
一般来说,它持有:
binom(n, k) = if (k == 0 || k == n) 1 else binom(n - 1, k - 1) * n / k
如果你想在线性时间内计算它,那么你必须确保每个中间结果都是一个整数。 现在,
binom(n - k + 1, 1)
当然是一个整数(它只是n - k + 1
)。 从这个数字开始,并将两个参数都加 1,您可以通过以下中间步骤得出binom(n, k)
:
binom(n - k + 1, 1)
binom(n - k + 2, 2)
...
binom(n - 2, k - 2)
binom(n - 1, k - 1)
binom(n, k)
这意味着您必须以正确的顺序“累积”,从1
到k
,而不是从k
到1
- 然后保证所有中间结果对应于实际二项式系数,因此是整数(不是分数)。 这是尾递归函数的样子:
def binom(n: Int, k: Int): Int = {
require(0 <= k && k <= n)
@annotation.tailrec
def binomtail(nIter: Int, kIter: Int, ac: Int): Int = {
if (kIter > k) ac
else binomtail(nIter + 1, kIter + 1, (nIter * ac) / kIter)
}
if (k == 0 || k == n) 1
else binomtail(n - k + 1, 1, 1)
}
小视觉测试:
val n = 12
for (i <- 0 to n) {
print(" " * ((n - i) * 2))
for (j <- 0 to i) {
printf(" %3d", binom(i, j))
}
println()
}
印刷:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1
1 11 55 165 330 462 462 330 165 55 11 1
1 12 66 220 495 792 924 792 495 220 66 12 1
看起来不错,如果需要,可以将其与此进行比较。
Andrey Tyukin 的优秀示例会因较大的 n 而失败,比如 binom(10000, 2),但可以很容易地适应使用 BigInt。
def binom(n: Int, k: Int): BigInt = {
require(0 <= k && k <= n)
@annotation.tailrec
def binomtail(nIter: Int, kIter: Int, ac: BigInt): BigInt = {
if (kIter > k) ac
else binomtail(nIter + 1, kIter + 1, (nIter * ac) / kIter)
}
if (k == 0 || k == n) 1
else binomtail(n - k + 1, 1, BigInt(1))
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.