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

如何在C语言中生成符合指定概率要求的范围随机数?

这问题挺典型的,用标准库的rand()就能搞定,分两种思路给你讲,看哪种更贴合你的需求:

方法一:概率动态控制法(长期占比稳定<20%)

如果不需要精确控制负数的绝对数量,只要求整体占比长期低于20%,可以用概率判断的方式动态生成:

核心逻辑是:每次生成随机数前,先判断「这次要不要生成负数」——给负数分配19%的概率(刚好小于20%),剩下81%的概率生成非负数(0到100)。

完整代码示例

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    // 初始化随机种子,只需要调用一次!
    srand(time(NULL));
    
    const int total_num = 200;
    const int negative_prob_threshold = 19; // 19%的概率生成负数

    for (int i = 0; i < total_num; i++) {
        int num;
        // 先判断生成负数还是非负数
        if (rand() % 100 < negative_prob_threshold) {
            // 生成-100到-1的负数:先取1-100,再加负号
            num = -(rand() % 100 + 1);
        } else {
            // 生成0到100的非负数:0到100共101个数,所以取模101
            num = rand() % 101;
        }
        printf("%d ", num);
        if ((i+1) % 10 == 0) printf("\n"); // 每10个换行,方便查看
    }

    return 0;
}

细节说明

  • 用rand() % 100得到0-99的均匀随机数,和19比较,相当于给负数分配19%的概率,严格小于20%;如果想更接近20%,可以改成(double)rand()/RAND_MAX < 0.199,用浮点判断更精确。
  • 生成负数时,rand() % 100 +1得到1-100,再加负号就变成-1到-100,避免生成0。
方法二:精确数量控制法(占比严格<20%)

如果需要严格控制负数的数量(比如最多39个,39/200=19.5%<20%),可以先生成指定数量的负数和非负数,再打乱顺序,保证随机性:

完整代码示例

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// Fisher-Yates洗牌算法,打乱数组顺序
void shuffle(int arr[], int size) {
    for (int i = size - 1; i > 0; i--) {
        int j = rand() % (i + 1);
        // 交换arr[i]和arr[j]
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

int main() {
    srand(time(NULL));
    
    const int total_num = 200;
    const int max_negative = 39; // 最多39个负数,占比19.5%
    int nums[total_num];

    // 先生成39个负数
    for (int i = 0; i < max_negative; i++) {
        nums[i] = -(rand() % 100 + 1);
    }
    // 再生成161个非负数
    for (int i = max_negative; i < total_num; i++) {
        nums[i] = rand() % 101;
    }
    // 打乱数组,避免前39个全是负数
    shuffle(nums, total_num);

    // 输出结果
    for (int i = 0; i < total_num; i++) {
        printf("%d ", nums[i]);
        if ((i+1) % 10 == 0) printf("\n");
    }

    return 0;
}

细节说明

  • Fisher-Yates洗牌算法是高效且公平的打乱方式,能保证每个元素的位置都是随机的。
  • 这种方法可以精确控制负数数量,完全满足「占比小于20%」的要求,适合对数量有严格限制的场景。
额外注意事项
  • 随机种子srand(time(NULL))只需要调用一次,不要放在循环里,否则会因为时间精度问题导致随机数重复。
  • 如果你的系统中RAND_MAX很小(比如16位系统的32767),rand() % 101的偏差可以忽略;如果追求极致均匀,可以用拒绝采样法(比如生成随机数如果大于等于101*(RAND_MAX/101)就重新生成),不过对这个场景来说没必要。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:44:34