利用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秒,差距有点大。

⚠️ **GitHub.com Fallback** ⚠️