如何使用C#计算大因子? Win 7中的Windows计算器在Factorial(3500)溢出。作为编程和数学问题,我有兴趣知道如何在C#中计算更大数字(20000,可能)的阶乘。有什么指针吗?
[编辑]我刚刚在Win 2k3上使用了一个计算结果,因为我记得在Win 2k3上做了一个更大的因子。我对事情的发展方式感到惊讶。
Win2k3上的Calc甚至可以处理大数字。我试过了!50000我得到了答案,3.3473205095971448369154760940715e + 213236
我做完这一切的速度非常快。
这里的主要问题不仅是找出合适的数据类型,还要有点数学。如果我尝试在C#[递归或循环]中编写一个简单的因子代码,那么性能真的很糟糕。获得答案需要几秒钟。 Windows 2k3(或XP)中的计算如何在不到10秒的时间内执行如此巨大的因子?有没有其他方法在C#中以编程方式计算factorial?
答案 0 :(得分:20)
查看BigInteger
结构:
http://msdn.microsoft.com/en-us/library/system.numerics.biginteger.aspx
也许这可以帮助您实现此功能。
CodeProject在http://www.codeproject.com/KB/cs/biginteger.aspx有一个旧版本框架的实现。
答案 1 :(得分:11)
如果我尝试在C#[递归或循环]中编写一个简单的因子代码,性能非常糟糕。获得答案需要几秒钟。
让我们在这里进行一个快速的数量级计算,以实现执行n次乘法的阶乘。假设我们是最后一步。 19999!约为2 18 位。 20000约为2 5 位;我们假设它是一个32位整数。因此,最终的乘法包括添加最多2个 5 部分结果,每个结果大约2个 18 位长。因此,位操作的数量将大约为2 23 。
那是最后一个阶段;在每个阶段将有20000 = 2 16 这样的操作,因此总共约2 39 操作。其中一些当然会更便宜,但我们在这里要达到一个数量级。
现代处理器每秒执行大约2次 32 操作。因此,获得结果大约需要2 7 秒。
当然,大整数图书馆作家并不天真;他们利用芯片的能力并行进行多个位操作。他们可能在32位块中进行数学运算,加速因子为2 5 。因此,我们的总数量级计算是需要大约2 2 秒才能得到结果。
2 2 是4.所以你的观察结果是需要几秒钟才能得到一个结果。
Windows 2k3(或XP)中的计算如何在不到10秒的时间内执行如此巨大的因子?
我不知道。可能在利用芯片上的数学运算时极为聪明。或者,使用非天真算法计算阶乘。或者,他们可能正在使用斯特林的近似并得到一个不精确的结果。
在C#中是否有其他以编程方式计算factorial的方法?
不确定。如果您关心的只是数量级,那么您可以使用斯特林的近似值。如果您关心确切的值,那么您将不得不计算它。
答案 2 :(得分:8)
存在复杂的计算算法,可以有效地计算大型,任意精度数的阶乘。例如,Schönhage–Strassen algorithm允许您对任意大整数执行渐近快速乘法。 / p>
例如,Mathematica在不到1秒的时间内在我的机器上计算22000!
。 reference.wolfram.com上的Implementation Notes页面声明:
(Mathematica's) n! uses an
O(log(n) M(n))
algorithm of Schönhage based on dynamic decomposition to prime powers.
不幸的是,这些算法的实现既复杂又容易出错。您可能更明智地许可Mathematica(或类似产品)的副本满足您的功能和性能需求)并使用它或.NET programming interface来执行计算。
答案 3 :(得分:5)
答案 4 :(得分:4)
使用System.Numerics BigInteger
var bi = new BigInteger(1);
var factorial = 171;
for (var i = 1; i <= factorial; i++)
{
bi *= i;
}
将计算为
1241018070217667823424840524103103992616605577501693185388951803611996075221691752992751978120487585576464959501670387052809889858690710767331242032218484364310473577889968548278290754541561964852153468318044293239598173696899657235903947616152278558180061176365108428800000000000000000000000000000000000000000
50000!它需要几秒钟来计算,但似乎有效,结果是一个213237的数字,这也是Wolfram所说的。
答案 5 :(得分:1)
您可能必须实现自己的任意精度数字类型。
有各种方法。可能不是最有效的,但也许最简单的是拥有可变长度的byte(unsigned char)数组。每个元素代表一个数字。理想情况下,这将包含在一个类中,然后您可以添加一个方法,让您将该数字乘以另一个任意精度数。与标准C#整数相乘可能也是一个好主意,但实现起来有点棘手。
答案 6 :(得分:1)
你需要一个特殊的大号库。 This link引入了System.Numeric.BigInteger类,并且顺便提供了一个计算阶乘的示例程序。但是不要使用这个例子!如果你像这样递归,你的筹码将会变得非常可怕。只需编写一个for循环来进行乘法运算。
答案 7 :(得分:1)
由于他们没有将结果提供给最后一位数字,因此他们可能会使用某种近似值“作弊”。 查看http://mathworld.wolfram.com/StirlingsApproximation.html 使用斯特林公式,您可以计算(近似值)对数时间n的阶乘。当然,它们也可能有一个字典,其中每个n达到一百万的预先计算的factorial(n)值,使计算器显示结果非常快。
答案 8 :(得分:1)
这个答案涵盖了计算和表示n!
的基本.Net类型的限制计算支持乘法的“SomeType”的阶乘的基本代码:
SomeType factorial = 1;
int n = 35;
for (int i = 1; i <= n; i++)
{
factorial *= i;
}
内置数字类型的限制:
short
- 正确的结果最多7个!之后的结果不正确,代码返回0开始18(类似于int)int
- 正确的结果最多12个!之后的结果不正确,代码从34开始返回0(Why computing factorial of realtively small numbers (34+) returns 0)float
- 精确的结果,最多14个!,之后正确但不精确,从35开始返回无穷大long
- 正确的结果最多20个!之后的结果不正确,代码从66开始返回0(类似于int
)double
- 精确的结果,最多22个!,之后正确但不精确,从171开始返回无穷大BigInteger
- 精确度和上限仅由内存使用量设置。注意:整数类型很快就会溢出并开始产生不正确的结果。实际上,如果您需要任何实际用法的因子long
是要去的类型(最多20个!),如果您不能指望数量有限 - BigInteger
是.Net Framework中提供的唯一类型提供精确的结果(虽然没有内置优化的n!方法,因此对于大数字来说很慢)
答案 9 :(得分:0)
我不知道如何在没有任意精度算术的语言中做到这一点。我想一个开始可能是计算5和2的因子,从产品中删除它们,并在最后添加这些零。
你可以看到有很多。
>>> factorial(20000)
<<non-zeroes removed>>0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000L