C++ 寻找阶乘的有效方法

C++ 寻找阶乘的有效方法,c++,data-structures,C++,Data Structures,除了正常的递归函数和循环方法外,寻找数字阶乘的有效方法是什么?由于普通方法产生输出的时间太长,有没有办法比递归和循环方法减少时间复杂度?如果没有,为什么?79!是1.711E98您只需要79个数字的列表即可使用查找表。 阶乘列在:整数格式或科学格式,因此从79开始,它只是剪切和粘贴!是1.711E98您只需要79个数字的列表即可使用查找表。 阶乘列在:整数格式或科学格式,因此如果要计算多个阶乘值,只需剪切和粘贴即可,然后可以选择在执行过程中缓存这些值 如果你只需要一次factorialn的计算,

除了正常的递归函数和循环方法外,寻找数字阶乘的有效方法是什么?由于普通方法产生输出的时间太长,有没有办法比递归和循环方法减少时间复杂度?如果没有,为什么?

79!是1.711E98您只需要79个数字的列表即可使用查找表。
阶乘列在:整数格式或科学格式,因此从79开始,它只是剪切和粘贴!是1.711E98您只需要79个数字的列表即可使用查找表。
阶乘列在:整数格式或科学格式,因此如果要计算多个阶乘值,只需剪切和粘贴即可,然后可以选择在执行过程中缓存这些值

如果你只需要一次factorialn的计算,那么循环可能是你能得到的最好的方法。通过一次计算两个或四个乘法的循环展开,您可能会从处理器中获得更多信息,但这不太可能适用于非常大的阶乘,因为乘法本身就是一系列冗长的指令


就我所知,没有神奇的数学可以计算出12*13*14*15的序列,或者比将它们相乘更快的序列

如果要计算多个阶乘值,则可以在执行过程中缓存这些值

如果你只需要一次factorialn的计算,那么循环可能是你能得到的最好的方法。通过一次计算两个或四个乘法的循环展开,您可能会从处理器中获得更多信息,但这不太可能适用于非常大的阶乘,因为乘法本身就是一系列冗长的指令


就我所知,没有神奇的数学可以计算出12*13*14*15的序列,或者比将它们相乘更快的序列

您可以使用来评估一个大阶乘。

您可以使用来评估一个大阶乘。

因为您的一条评论说您希望找到100000!,这个答案涵盖了巨大的因素

如果您不需要确切答案,可以使用

如果你想要一个精确的答案,你需要使用一个任意精度的数学软件包,比如GMP

因为你的一条评论说你想找到100000!,这个答案涵盖了巨大的因素

如果您不需要确切答案,可以使用

如果你想要一个精确的答案,你需要使用一个任意精度的数学软件包,比如GMP
不,不是真的。如果您关心运行时成本,可以通过一个查找表来减少,该表要求您使用预先计算的值

存储每个阶乘可能需要太多内存,所以让我们存储每个k:th阶乘。 这将要求程序在运行时执行多达k次乘法

假设您的运行时性能要求将每个阶乘限制为1000次乘法。然后您需要预先计算并存储1000!,2000!, 3000! 以此类推,如果达到您希望支持的可用内存上限,则会限制您

由于阶乘很快会比本机数据类型大,因此需要一个能够处理大量数据的类。我假设存在这样一个类,它被称为BigInteger


不,不是真的。如果您关心运行时成本,可以通过一个查找表来减少,该表要求您使用预先计算的值

存储每个阶乘可能需要太多内存,所以让我们存储每个k:th阶乘。 这将要求程序在运行时执行多达k次乘法

假设您的运行时性能要求将每个阶乘限制为1000次乘法。然后您需要预先计算并存储1000!,2000!, 3000! 以此类推,如果达到您希望支持的可用内存上限,则会限制您

由于阶乘很快会比本机数据类型大,因此需要一个能够处理大量数据的类。我假设存在这样一个类,它被称为BigInteger


计算非常大的因子的最简单方法是使用 伽马函数。另一方面,它不会像以前那么快 其他人建议的查表;如果您使用的是内置 在类型中,您需要以下表格:

for 32 bits: 12 entries
for 64 bits: 20 entries
for float:   34 entries
for double: 170 entries
上表中可能存在一个“关一”错误。我写 这段代码可以非常快速地计算它们

对于double,也可能是float,通常的循环方法 无论如何,可能会引入太多舍入错误。如果你 不想使用表,你有C++11, exp lgama i+1应该可以做到这一点。如果你不 有了C++11,您可能仍然拥有lgama函数。它是 在C99中

如果你在处理某种扩展范围类型,你
可能必须为您的类型实现LGAMA和exp。

计算非常大的因子的最简单方法是使用 伽马函数。另一方面,它不会像以前那么快 助教 其他人提议的可撤销查阅;如果您使用的是内置 在类型中,您需要以下表格:

for 32 bits: 12 entries
for 64 bits: 20 entries
for float:   34 entries
for double: 170 entries
上表中可能存在一个“关一”错误。我写 这段代码可以非常快速地计算它们

对于double,也可能是float,通常的循环方法 无论如何,可能会引入太多舍入错误。如果你 不想使用表,你有C++11, exp lgama i+1应该可以做到这一点。如果你不 有了C++11,您可能仍然拥有lgama函数。它是 在C99中

如果你在处理某种扩展范围类型,你

可能必须为您的类型实现lgamma和exp。

您试图使用阶乘解决的问题是什么?请查看您还有多长时间?gmp中的一个简单实现在我的机器上只需0.9秒就可以完成。显然,不同的处理器/机器将具有不同的性能。您试图使用阶乘解决的问题是什么?看看您还有多长时间?gmp中的一个简单实现在我的机器上用0.9秒就完成了。显然,不同的处理器/机器将有不同的性能。我不完全相信在大数数学中计算大指数和平方根等会容易得多。我对字符串数学的天真方法目前是12分钟做100000!10K相对简单,耗时约5秒,但随着数字变长,缓存不够大,复制需要更长时间,等等,使用lnn!=n*lnn-n形式的英镑,n=10000我们得到ln10000!~=82103那么一万假设我的高中数学没有让我不及格。所以很快就能得到一个非常粗略的近似值。我同意如果你想要全部35657位数的答案,英镑不是最好的选择。但是现在我们知道我们可以用GMP在3701个4字节的内存中计算出答案。我不完全相信在大数数学中计算大指数和平方根等要容易得多。我对字符串数学的天真方法目前是12分钟做100000!10K相对简单,耗时约5秒,但随着数字变长,缓存不够大,复制需要更长时间,等等,使用lnn!=n*lnn-n形式的英镑,n=10000我们得到ln10000!~=82103那么一万假设我的高中数学没有让我不及格。所以很快就能得到一个非常粗略的近似值。我同意如果你想要全部35657位数的答案,英镑不是最好的选择。但现在我们知道,我们可以使用GMP在3701个4字节的内存中计算答案。查找表正是我所建议的。但我不知道他从哪里得到79。根据我的计算,很容易出现一个错一个错,对于32位整数,12个条目就足够了;对于64位,20,IEEE浮点34和IEEE双170。查找表正是我所建议的。但我不知道他从哪里得到79。根据我的计算,很容易出现一个错一个错,对于32位整数,12个条目就足够了;对于64位,20,对于IEEE浮点34和IEEE双170。当n进入1000的数字类型时,做指数、对数等也会变得相当混乱,因为它们超出了整数的数值范围。@Matstpeterson但任何扩展精度/大小包都应该已经有了它们。使用这个或伽马函数的东西肯定会比循环更好,尽管它们的编程肯定更复杂。当n进入1000的数字类型时,做指数、对数等也会变得相当混乱,因为它们超出了整数的数值范围,所以任何扩展的精度/大小包都应该已经有了它们。使用这个函数或gamma函数的东西肯定会比仅仅循环执行得更好,尽管它们对于编程来说显然更复杂。gamma i-1==fact i。计算gamma并不一定简单,但对于大i来说,它比仅仅乘法要快得多,而且不会得到循环中得到的累积舍入误差:请记住,每次得到舍入误差时,它都会乘以以下所有项。只会得到浮点舍入误差。浮点数不能超过几百个左右。通常的双精度大约是170。但即使在那里,使用gamma也可以避免这个问题。我不太熟悉gamma是如何计算的,但快速浏览一下g++库中的源代码会给人一种印象,它肯定比On快,这就是循环将给出的结果。是的,但它也不准确-我们说的是100000!,不是170。这远远超出了我熟悉的所有浮点范围,大约是35K位。这需要大量的计算。我认为伽马是用其他地方的斯特林近似计算的。在这种情况下,它会遇到同样的问题,即不准确,而且计算起来相当复杂
E我用gmp编写了一个简单的实现,计算100000只需要0.9秒!迭代使用所有数字,然后添加0.8s以实际显示它,但是如果我将它发送到/dev/null…使用gamma应该比乘法更精确。至于一百万!,假设有某种BigInteger类,那么它是否适合存储在内存中?无论如何,我肯定会实现gamma函数并使用它,而不是在乘法上循环。gamma I-1==事实I。计算gamma并不一定简单,但对于大i来说,它比仅仅乘法要快得多,而且不会得到循环中得到的累积舍入误差:请记住,每次得到舍入误差时,它都会乘以以下所有项。只会得到浮点舍入误差。浮点数不能超过几百个左右。通常的双精度大约是170。但即使在那里,使用gamma也可以避免这个问题。我不太熟悉gamma是如何计算的,但快速浏览一下g++库中的源代码会给人一种印象,它肯定比On快,这就是循环将给出的结果。是的,但它也不准确-我们说的是100000!,不是170。这远远超出了我熟悉的所有浮点范围,大约是35K位。这需要大量的计算。我认为伽马是用其他地方的斯特林近似计算的。在这种情况下,它会遇到同样的问题,即不准确,而且计算起来相当复杂。我用gmp编写了一个简单的实现,计算100000只需要0.9秒!迭代使用所有数字,然后添加0.8s以实际显示它,但是如果我将它发送到/dev/null…使用gamma应该比乘法更精确。至于一百万!,假设有某种BigInteger类,那么它是否适合存储在内存中?无论如何,我肯定会实现gamma函数并使用它,而不是在倍数上循环。