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

C#生成随机数计算出现负数结果的原因排查

问题:随机数计算偶尔出现负数的原因?

我尝试生成20个1-100之间的随机数,通过声明委托(Delegate)和事件(Event)实现逻辑:若存在大于50的数则将所有数相乘,否则求和。代码如下:

using System;
using System.Linq;

namespace ConsoleApp
{
    class Program
    {
        // Delegate tanımla
        public delegate int MyDelegate(int[] arr);
        public event MyDelegate OnResultCalculated;

        static void Main(string[] args)
        {
            Program p = new Program();

            // 1-100 arasında 20 adet rastgele sayı üret
            Random rnd = new Random();
            int[] numbers = Enumerable.Range(1, 100).OrderBy(x => rnd.Next()).Take(20).ToArray();

            // Eğer 50'den büyük sayı varsa çarp, yoksa topla
            int result = numbers.Any(x => x > 50)? p.Multiply(numbers) : p.Add(numbers);

            // Event'i tetikle
            p.OnResultCalculated?.Invoke(numbers);
            Console.WriteLine(result);
            Console.ReadLine();
        }

        public int Multiply(int[] arr)
        {
            return arr.Aggregate(1, (a, b) => a * b);
        }

        public int Add(int[] arr)
        {
            return arr.Sum();
        }
    }
}

代码可正常运行,但偶尔会得到负数结果,请问问题出在哪里?


解答

问题的核心是整数溢出:

  • C# 中int类型的取值范围是 -2^31 到 2^31-1(即 -2147483648 到 2147483647)。
  • 当计算20个1-100之间的数相乘时,哪怕是较小的数(比如连续20个5相乘:5^20=95367431640625),结果也远远超出了int的最大值。
  • .NET 默认在unchecked模式下运行,整数溢出不会抛出异常,而是按照二进制补码规则循环计算,最终得到负数结果。

修复方案

方案1:改用更大范围的数值类型

把委托、Multiply方法的返回值类型改成long(取值范围 -9223372036854775808 到 9223372036854775807),能容纳更大的乘积:

// 修改委托类型
public delegate long MyDelegate(int[] arr);
public event MyDelegate OnResultCalculated;

// 修改Multiply方法
public long Multiply(int[] arr)
{
    return arr.Aggregate(1L, (a, b) => a * b);
}

// 主方法中接收结果的变量也改成long
long result = numbers.Any(x => x > 50) ? p.Multiply(numbers) : p.Add(numbers);

方案2:使用BigInteger处理超大数值

如果乘积可能超出long的范围(比如20个100相乘:100^20=10^40,远大于long的最大值),可以用System.Numerics.BigInteger类型:

首先添加对System.Numerics程序集的引用,然后修改代码:

using System.Numerics;

// 修改委托类型
public delegate BigInteger MyDelegate(int[] arr);
public event MyDelegate OnResultCalculated;

// 修改Multiply方法
public BigInteger Multiply(int[] arr)
{
    return arr.Aggregate(BigInteger.One, (a, b) => a * b);
}

// 主方法中接收结果的变量改成BigInteger
BigInteger result = numbers.Any(x => x > 50) ? p.Multiply(numbers) : new BigInteger(p.Add(numbers));

方案3:启用溢出检查(可选)

如果希望溢出时抛出异常而非静默产生错误结果,可以在代码中使用checked块:

public int Multiply(int[] arr)
{
    return checked(arr.Aggregate(1, (a, b) => a * b));
}

这样当溢出发生时会抛出OverflowException,方便及时发现问题,但不会解决结果负数的问题,只是提前暴露错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 09:10:33