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

1-45选6乐透号码与整数值双向转换算法实现(C#优先)

乐透彩票号码与整数双向互转低内存实现

这个需求的映射逻辑本质是组合数编码规则,不需要预存全量组合映射表,内存占用可忽略,单次转换时间复杂度固定为O(1)(因单注号码固定为6个,计算量恒定),完全可以替代高内存占用的全量预计算方案。

规则对齐

实现完全匹配给定的映射规则:

  • 单注包含6个1~45范围内的不重复号码,按从小到大排序后参与计算
  • 最小组合01-02-03-04-05-06对应序号1
  • 最大组合40-41-42-43-44-45对应序号8145060
  • 总组合数为C(45,6)=8145060,和规则定义一致

核心算法逻辑

号码转序号

  1. 将输入的6个号码从小到大排序,得到升序序列c₀<c₁<c₂<c₃<c₄<c₅
  2. 基于组合数累加计算0基偏移,最终+1得到1基序号:
    序号 = C(c₀-1,1) + C(c₁-1,2) + C(c₂-1,3) + C(c₃-1,4) + C(c₄-1,5) + C(c₅-1,6) + 1
    其中C(n,k)为组合数公式,代表从n个元素选k个的方案数,当n<k时C(n,k)=0

序号转号码

  1. 将输入的1基序号减1转为0基偏移量m
  2. 从最大选位k=6开始倒推,每次找到满足C(c,k) ≤ m的最大整数c,将c+1(转1基)作为当前位的号码
  3. 偏移量m减去C(c,k),k值减1,重复直到6个号码全部推导完成
  4. 最终得到的号码自然为升序排列,无需额外排序

C# 完整实现

public static class LottoConverter
{
    // 计算组合数C(n,k),n<k时直接返回0
    private static long Comb(int n, int k)
    {
        if (n < k || k < 0) return 0;
        if (k == 0 || k == n) return 1;
        k = Math.Min(k, n - k);
        long result = 1;
        for (int i = 1; i <= k; i++)
        {
            result = result * (n - k + i) / i;
        }
        return result;
    }

    /// <summary>
    /// 6个乐透号码转对应1基序号
    /// </summary>
    /// <param name="numbers">6个1-45范围的不重复整数</param>
    /// <returns>1-8145060范围的映射序号</returns>
    public static long NumbersToIndex(int[] numbers)
    {
        if (numbers.Length != 6)
            throw new ArgumentException("单注乐透需包含6个号码", nameof(numbers));
        
        var sorted = numbers.OrderBy(n => n).ToArray();
        for (int i = 0; i < 6; i++)
        {
            if (sorted[i] < 1 || sorted[i] > 45)
                throw new ArgumentOutOfRangeException(nameof(numbers), "号码取值范围必须为1-45");
            if (i > 0 && sorted[i] == sorted[i-1])
                throw new ArgumentException("号码不能重复", nameof(numbers));
        }

        long index = 1;
        for (int i = 0; i < 6; i++)
        {
            index += Comb(sorted[i] - 1, i + 1);
        }
        return index;
    }

    /// <summary>
    /// 1基序号转对应乐透号码
    /// </summary>
    /// <param name="index">1-8145060范围的映射序号</param>
    /// <returns>升序排列的6个乐透号码</returns>
    public static int[] IndexToNumbers(long index)
    {
        if (index < 1 || index > 8145060)
            throw new ArgumentOutOfRangeException(nameof(index), "序号取值范围必须为1-8145060");
        
        long m = index - 1;
        int[] result = new int[6];
        int k = 6;
        for (int i = 5; i >= 0; i--)
        {
            int c = k - 1;
            while (Comb(c + 1, k) <= m)
            {
                c++;
            }
            result[i] = c + 1;
            m -= Comb(c, k);
            k--;
        }
        return result;
    }
}

样例验证

  • 输入号码[1,2,3,4,5,6],转换得到序号1,符合规则
  • 输入号码[1,2,3,4,5,7],转换得到序号2,符合规则
  • 输入序号8145059,转换得到号码[39,41,42,43,44,45],符合规则
  • 输入序号8145060,转换得到号码[40,41,42,43,44,45],符合规则

该实现无全局预加载数据,运行时内存占用为固定常量,单次转换仅需最多几十次整数运算,批量转换性能远高于预计算查表方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 15:36:23