You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

生成完全数时输出负数问题排查及代码优化请求

问题分析与解决方案

核心问题:整数溢出

你遇到的负数结果是int类型溢出导致的,和List<T>无关。C#的int是32位有符号整数,最大值为2147483647(即2^31-1)。当生成第5个完全数时:

  • 对应素数p=17,梅森数是2^17-1=131071(素数)
  • 完全数计算为2^(17-1) * 131071 = 65536 * 131071 = 8589869056
    这个数值远超过int的最大值,溢出后会变成负数(符合二进制补码的溢出规则)。

代码优化方案

1. 替换整数类型为long

将所有涉及大数计算的变量从int改为long,long是64位有符号整数,最大值为9223372036854775807,能容纳前7个完全数。

修改后的代码:

List<long> GeneratePerfectNumbers(int upperbound)
{
    List<long> nums = new List<long>();
    for (int i = 2; i < upperbound; i++)
    {
        if (IsPrime(i))
        {
            // 用位运算替代Math.Pow,避免精度丢失
            long mersenneNumber = (1L << i) - 1;
            if (IsPrime(mersenneNumber))
            {
                long perfectNumber = (1L << (i - 1)) * mersenneNumber;
                nums.Add(perfectNumber);
            }
        }
    }
    return nums;
}

static bool IsPrime(long number)
{
    if (number <= 1)
        return false;
    // 提前处理偶数,减少循环次数
    if (number == 2)
        return true;
    if (number % 2 == 0)
        return false;

    // 仅遍历奇数,优化性能
    for (long i = 3; i <= Math.Sqrt(number); i += 2)
    {
        if (number % i == 0)
            return false;
    }
    return true;
}

2. 关键优化点说明

  • 替换Math.Pow为位运算:Math.Pow返回double类型,当i超过53时会丢失精度,位运算1L << i既保证精度又提升计算速度。
  • 素数判断优化:提前过滤偶数,循环仅遍历奇数,减少一半的迭代次数,提升素数检测效率。

测试验证

使用修改后的代码测试:

foreach (long j in GeneratePerfectNumbers(20))
{
    Console.WriteLine(j);
}

输出的前5个完全数为:
6, 28, 496, 8128, 33550336, 8589869056
均为正确值,无溢出问题。

进一步扩展(可选)

如果需要生成更大的完全数,64位long也会达到上限,此时可以使用System.Numerics.BigInteger类型,它支持任意大小的整数,但素数判断需要替换为更高效的算法(比如Miller-Rabin素性测试)。

内容的提问来源于stack exchange,提问作者Oscar Nguyen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 13:12:50