利用Skyiv.Numeric的BigInteger类计算大数阶乘 - l1t1/note GitHub Wiki
我让QWen3 根据我已有的Python程序思路编写利用BigInteger类的C#程序,如下所示,编译报错,不知为何我的.NET Framework v4.0.30319不带这个库。BigInteger结构文档说带的。
error CS0246: 未能找到类型或命名空间名称“BigInteger”(是否缺少 using 指令或程序集引用?)
然后我加入了一行using BigInteger = Skyiv.Numeric.BigInteger;
就实现了对C#本身BigInteger的平滑替换。
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Diagnostics;
using BigInteger = Skyiv.Numeric.BigInteger; //我只加入了此行
class Fact
{
static void Main()
{
int n = 100000;
Console.WriteLine("factorial_product_tree({0})", n);
Stopwatch sw = Stopwatch.StartNew();
BigInteger result = FactorialProductTree(n);
sw.Stop();
string s = result.ToString();
Console.WriteLine("Time: {0} seconds", sw.Elapsed.TotalSeconds);
Console.WriteLine("Length: {0}, First 20 digits: {1}", s.Length, s.Substring(0, Math.Min(20, s.Length)));
}
static BigInteger FactorialProductTree(int n)
{
if (n == 0 || n == 1)
return 1;
List<BigInteger> numbers = new List<BigInteger>();
for (int i = 1; i <= n; i++)
{
numbers.Add(i);
}
return ProductTree(numbers);
}
static BigInteger ProductTree(List<BigInteger> nums)
{
int length = nums.Count;
if (length == 1)
return nums[0];
if (length == 2)
return nums[0] * nums[1];
int mid = length / 2;
List<BigInteger> left = nums.GetRange(0, mid);
List<BigInteger> right = nums.GetRange(mid, length - mid);
// 可选:并行执行左右子树乘积(适用于多核CPU)
// var leftTask = Task.Run(() => ProductTree(left));
// var rightTask = Task.Run(() => ProductTree(right));
// return leftTask.Result * rightTask.Result;
BigInteger leftProduct = ProductTree(left);
BigInteger rightProduct = ProductTree(right);
return leftProduct * rightProduct;
}
}
编译命令行为
csc -define:DEBUG -optimize -out:fact10w.exe Fact.cs BigInteger.cs BigArithmetic.cs Utility.cs
以上程序计算10万的阶乘用时0.29秒,比如下的顺序相乘求阶乘快几百倍。
string RunTest(int n)
{
BigInteger a = 1, b;
for (int i = 2; i <= n; i++, a *= b) b = i;
return a.ToString();
}
后记:我自行在搜索引擎中找error CS0246的解决办法,查看微软.NET程序集文档,甚至用.net reflector 反编译工具查看System.Numerics.dll里面是有BigInteger的。花了很久没有结果。
而继续提问很快得到解答,看来,现在解决此类问题,问AI比人工搜索靠谱。
关键的编译选项是 /r:System.Numerics.dll
或/reference:System.Numerics.dll
, 就像gcc编译调用数学库的程序要加-lm参数一样。其实这个命令行参数csc /?就能看到解释 从指定的程序集文件引用元数据,但“程序集”这个名字对于不熟悉c#的我太陌生了。
csc -define:DEBUG -optimize -out:msfact10w.exe Fact.cs /r:System.Numerics.dll
编译结果是,System.Numerics的BigInteger速度不如Skyiv.Numeric.BigInteger。上述程序计算要用1秒,输出字符串还另要2秒,差距有点大。