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

PL/SQL生成1-3亿随机数分布不均问题咨询

解决Oracle PL/SQL生成1-3亿随机数位数分布不均的问题

问题原因

你用的floor(dbms_random.value(1, 300000000))是在数值范围上均匀随机采样,但不同位数对应的数值区间大小差异极大:

  • 1位数仅包含1-9(共9个数)
  • 2位数是10-99(90个数)
  • ...
  • 8位数是10000000-99999999(9000万个)
  • 9位数是100000000-300000000(2亿个)

数值区间越大,被采样到的概率越高,所以结果自然集中在8、9位数,低位数几乎不会出现。

解决方案:按位数区间均匀采样

要生成包含各位数的随机数,需要先随机选择位数(1-9),再在对应位数的数值范围内生成随机数,确保每个位数区间被选中的概率均等。

方案1:随机选择位数生成(各位数概率均等)

以下PL/SQL代码循环生成50个随机数,每次先随机选1-9的位数,再生成对应区间的数:

DECLARE
    v_digit NUMBER;
    v_random_num NUMBER;
BEGIN
    FOR i IN 1..50 LOOP
        -- 随机选取1-9的位数
        v_digit := FLOOR(DBMS_RANDOM.VALUE(1, 10));
        
        CASE v_digit
            WHEN 1 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(1, 10));
            WHEN 2 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(10, 100));
            WHEN 3 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(100, 1000));
            WHEN 4 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(1000, 10000));
            WHEN 5 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(10000, 100000));
            WHEN 6 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(100000, 1000000));
            WHEN 7 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(1000000, 10000000));
            WHEN 8 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(10000000, 100000000));
            WHEN 9 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(100000000, 300000001)); -- 包含3亿
        END CASE;
        
        DBMS_OUTPUT.PUT_LINE(v_random_num);
    END LOOP;
END;
/

方案2:精准控制各位数数量

如果需要确保每个位数的数都有固定数量(比如1-9位各至少5个),可以先分配数量再生成:

DECLARE
    TYPE digit_count_type IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
    v_digit_counts digit_count_type;
    v_digit NUMBER;
    v_random_num NUMBER;
    v_total_num CONSTANT NUMBER := 50;
BEGIN
    -- 初始化:1-9位各分配5个,共45个,剩余5个随机分配
    FOR d IN 1..9 LOOP
        v_digit_counts(d) := 5;
    END LOOP;
    
    -- 分配剩余的5个名额
    FOR i IN 1..(v_total_num - 45) LOOP
        v_digit := FLOOR(DBMS_RANDOM.VALUE(1, 10));
        v_digit_counts(v_digit) := v_digit_counts(v_digit) + 1;
    END LOOP;
    
    -- 按分配数量生成随机数
    FOR d IN 1..9 LOOP
        FOR j IN 1..v_digit_counts(d) LOOP
            CASE d
                WHEN 1 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(1, 10));
                WHEN 2 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(10, 100));
                WHEN 3 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(100, 1000));
                WHEN 4 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(1000, 10000));
                WHEN 5 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(10000, 100000));
                WHEN 6 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(100000, 1000000));
                WHEN 7 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(1000000, 10000000));
                WHEN 8 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(10000000, 100000000));
                WHEN 9 THEN v_random_num := FLOOR(DBMS_RANDOM.VALUE(100000000, 300000001));
            END CASE;
            DBMS_OUTPUT.PUT_LINE(v_random_num);
        END LOOP;
    END LOOP;
END;
/

注意事项

  • 方案1中,虽然各位数概率均等,但仍可能出现某位数暂时没出现的情况(概率极低),如果需要绝对保证各位数都有,优先用方案2。
  • 9位数的上限是3亿,所以对应的区间是100000000到300000001(因为dbms_random.value的右边界是开区间,所以要写300000001才能包含300000000)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 19:15:32