使用原始运算符查找 N 到 K 深度的阶乘

Using primitive operators to find factorial of N up to K depth

提问人:mks 提问时间:8/22/2020 最后编辑:martineaumks 更新时间:11/15/2023 访问量:1640

问:

使用以下方法难以提出解决方案:

  1. 迭代/控制流和
  2. 积累。

不仅仅是一个解决方案,更希望有一个带有提示和解释的答案。

def falling(n, k):
    """Compute the falling factorial of N to depth K.

    >>> falling(6, 3)  # 6 * 5 * 4
    120
    >>> falling(4, 3)  # 4 * 3 * 2
    24
    >>> falling(4, 1)  # 4
    4
    >>> falling(4, 0)
    1
    """
    fact = n
    i = 0    
    while i <= k:
        fact = fact * fact - 1
        i += 1
        n -= 1
    return fact
python while-loop 阶乘

评论

0赞 deadshot 8/22/2020
你的代码有什么问题?
0赞 001 8/22/2020
请注意,这等效于 。不确定这是你想要的。fact * fact - 1(fact * fact) - 1
0赞 Barmar 8/22/2020
@deadshot 除了完全错误的事实之外?
0赞 mks 8/22/2020
这无济于事。我的代码中的逻辑完全关闭了。我需要理解其中的逻辑。
0赞 deadshot 8/22/2020
@Barmar出了什么问题????

答:

-1赞 Timbolt 8/22/2020 #1
def falling(n, k):
    """Compute the falling factorial of N to depth K.

    >>> falling(6, 3)  # 6 * 5 * 4
    120
    >>> falling(4, 3)  # 4 * 3 * 2
    24
    >>> falling(4, 1)  # 4
    4
    >>> falling(4, 0)
    1
    """
    
    if k == 0:
        return 1

    return_value = 1

    counter = 0

    while counter < k:
        return_value = return_value * (n-counter)
        counter += 1

    return return_value

忽略 k=0,您想将 k 个数字相乘,从 n 开始,以 n-k 结尾。上面循环 k 次,由于 i 将从 1 开始递增 0,因此您可以简单地从 n 中减去它以获得下一个要乘以的数字。

编辑:确保 k=0 始终通过提前返回来返回 1

编辑2:删除内置范围功能

编辑3:确保深入 k

评论

0赞 mks 8/22/2020
这太棒了。需要注意的是,它使用的是内置函数范围。
0赞 Timbolt 8/22/2020
我是误解了您不想使用它,还是只是想了解有关该内置函数的更多信息?
0赞 mks 8/22/2020
Timbolt,我只想使用原始运算符和 if/while 循环。没有内置功能,如范围等。
0赞 Timbolt 8/22/2020
我改了,这是你想要的吗?我假设您不希望范围函数更好地理解计算?否则,它只会让它更混乱。
0赞 mks 8/22/2020
Timbolt,谢谢你的帮助。这个问题有点棘手;它要求你做一个阶乘,最多 K 次,而不是 K 次。因此,对于 N=6 和 K=3,它有效,因为 N - K = 3 是正确的,因为我们想要 6 到 5, 4 的阶乘。但是,N=4 和 K=1 呢?当 N - K 仍然是 3 时,我们最终会得到 4 * 3 * 2 = 12 - 这是我们不想要的。我们想要 1 个深度,即 4 * 1 = 4
0赞 hisokareddy 8/22/2020 #2

由于您不想要解决方案,而是想要代码失败的原因,因此 ILL 会为您提供一些指示

逻辑是错误的,这就是原因

  • 事实在每次迭代中都在更新,
  • 仔细检查 while 条件 i < k 还是 i <= k?

评论

0赞 mks 8/22/2020
指针 1) 是的,我想知道如何保存(累积)结果。指针 2) 下面的代码由 Timbolt 通过返回静态 1 解决了 k 为 0 的问题。正如你所注意到的,我的问题在这里。1)如果必须使用while循环,我如何累积总数?2) 或者每次迭代都用 n -1 做 for 循环 K 次?
0赞 hisokareddy 8/23/2020
为了保留该值,只需使用另一个变量,它看起来会是这样的 res = res * fact,之后你需要在每次迭代中将 fact 递减 1,所以 fact = fact - 1(将 res 初始化为 1 ),此外,您需要查看正好 k 次,所以它应该是 i < k 如果你的 k 是 0,你可以根据你的偏好在循环之前返回 0 或 1
0赞 Yusuf Adel 9/11/2022 #3

首先,您需要生成数字以应用乘法

例如,我们通过使用# 6 * 5 * 4

range(n, k, -1)=> 例如,对于 (n, k) = (6, 3) 将是 [6, 5, 4]

然后用 .reduce

def falling(n, k):
    return reduce(lambda x, y: x * y, list(range(n, k, -1)))

# more readable

```python
def falling(n, k):
    from operator import mul
    return reduce(mul, list(range(n, k, -1)))

lambda x, y: x * y=> 只得到两个数字的乘积

在 Python 3.8+ 中

你会使用math.prod()

def factorial_with_depth(n, k):
    """Compute the falling factorial of n to depth k."""
    from math import prod  # python 3.8+
    return prod(range(n, k, -1))
0赞 Joren 11/15/2023 #4

您说的是“下降阶乘”,也称为“下降功率”。它通常发音为“n to the k falling”。

整数参数

对于正整数参数,它可以计算为阶乘的比率:。在 Python 中,这转换为:n! / (n - k)!

import math

def falling(n: int, k: int) -> int:
    assert k >= 0
    return math.factorial(n) // math.factorial(n - k)

举例说明:

>>> [falling(6, k) for k in range(6)]
[1, 6, 30, 120, 360, 720]

或者,也可以通过将二项式系数 “n 选择 k” 乘以 来计算,即 。n!math.comb(n, k) * math.factorial(k)

真实论据

如果您有实数参数,则可以使用 gamma 函数,它将阶乘扩展到实数域。由于浮点数可能会溢出,因此最好使用 gamma 函数的对数:

def falling_real(x: float, n: int | float) -> float:
    return math.exp(math.lgamma(x + 1) - math.lgamma(x - n + 1))

例如:

>>> falling_real(math.e, math.pi)
2.7574468451854215

请注意,这可能会导致轻微的数值错误:

>>> [falling_real(6, k) for k in range(6)]
[1.0, 6.000000000000003, 30.000000000000057, 120.00000000000009, 360.0000000000007, 720.0000000000008]