php随机数总计3000

发布于 2025-01-10 01:55:58 字数 1437 浏览 0 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

薯片软お妹 2025-01-17 01:55:58

您的问题是 3000 / 630 = 4.76 与 1-20 之间的平均值相差甚远。我们可以做的是限制随机数的范围以适应这种情况,并获得平均和接近最大和的分布倾斜

给定所需的最大平均值 4.76,我们可以生成 1/4 之间的随机数 1-203/4 > 在 1-4 之间倾斜分布:

function get_slanted_rands() {
        
    $rands = [];
    
    for($i = 1; $i <= 630; $i++) {
        // For every 4th iteration, get random from the full range
        $rands[] = $i % 4 === 0 
            ? mt_rand(1,20)
            : mt_rand(1,4);
    }
    
    $sum = array_sum($rands);
    
    // If the sum is over the max, recall:
    if($sum > 3000) {
        return get_slanted_rands();
    }
    // Log the average for debugging:
    $avg = round($sum / count($rands), 2);
    return compact('sum', 'avg', 'rands');
}

请注意,函数检查总和并在总和超过 3000 的奇怪情况下调用自身。在典型的调用中,总和 3000不会超过上述“校准”——因为我们以 1:3 的比例分割以支持较低的范围。但随机就是随机,所以不能保证“平均”。

让我们测试这个装置 100 次迭代,看看我们得到了什么:

$test = [];
for($t = 1; $t <= 100; $t++) {
    $test[] = get_slanted_rands();
}

$sums = array_column($test, 'sum');
rsort($sums);
echo "==== SUMS ====\n" . implode(', ', $sums) . "\n\n";

$avgs = array_column($test, 'avg');
rsort($avgs);
echo "==== AVGS ====\n" . implode(', ', $avgs);

这会产生以下结果(反向排序),总和在 2600+ 到 3000 之间,平均值在 4.75 到 4.19 之间。 (平均而言,~1:100 迭代超过 3000 并被召回。)

==== SUMS ====
2993, 2985, 2975, 2969, 2959, 2947, 2941, 2933, 2926, 2919, 2919, 2917, 2911, 2909, 2908, 2904, 2903, 2901, 2894, 2894, 2892, 2886, 2884, 2884, 2882, 2881, 2879, 2876, 2871, 2869, 2867, 2863, 2861, 2853, 2852, 2852, 2851, 2851, 2850, 2848, 2844, 2843, 2842, 2838, 2838, 2837, 2837, 2837, 2836, 2834, 2834, 2826, 2826, 2825, 2820, 2814, 2813, 2812, 2802, 2801, 2799, 2799, 2799, 2798, 2796, 2795, 2792, 2789, 2789, 2787, 2784, 2784, 2784, 2783, 2778, 2778, 2776, 2768, 2767, 2764, 2762, 2754, 2754, 2747, 2743, 2737, 2736, 2728, 2727, 2724, 2723, 2721, 2719, 2718, 2707, 2706, 2690, 2673, 2642

==== AVGS ====
4.75, 4.74, 4.72, 4.71, 4.7, 4.68, 4.67, 4.66, 4.64, 4.63, 4.63, 4.63, 4.62, 4.62, 4.62, 4.61, 4.61, 4.6, 4.59, 4.59, 4.59, 4.58, 4.58, 4.58, 4.57, 4.57, 4.57, 4.57, 4.56, 4.55, 4.55, 4.54, 4.54, 4.53, 4.53, 4.53, 4.53, 4.53, 4.52, 4.52, 4.51, 4.51, 4.51, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.49, 4.49, 4.48, 4.48, 4.47, 4.47, 4.46, 4.45, 4.45, 4.44, 4.44, 4.44, 4.44, 4.44, 4.44, 4.43, 4.43, 4.43, 4.42, 4.42, 4.42, 4.42, 4.42, 4.41, 4.41, 4.41, 4.39, 4.39, 4.39, 4.38, 4.37, 4.37, 4.36, 4.35, 4.34, 4.34, 4.33, 4.33, 4.32, 4.32, 4.32, 4.32, 4.31, 4.3, 4.3, 4.27, 4.24, 4.19

如果您认为平均应该接近 3000,您可以随时调整倾斜条件...或者简单地添加带有“最小总和”检查的召回条件并“暴力”它。但这足以让您了解总体思路:您需要根据“目标总和的平均值”的要求生成有限范围内的随机数。 3v4l 演示:https://3v4l.org/fG74X


最后,您获得的发行版示例。给出“数字” => 630 个集合中的“实例”。这里严重倾向于 1、2、3、4 — 这就是满足您的规格的方式

$nums = get_slanted_rands();
$distribution = array_count_values($nums['rands']);
arsort($distribution);
print_r($distribution);

// yields:
  [3] => 143
  [4] => 125
  [2] => 125
  [1] => 110
  [8] => 13
  [9] => 12
  [18] => 12
  [19] => 10
  [11] => 9
  [5] => 8
  [17] => 8
  [14] => 7
  [12] => 7
  [10] => 7
  [16] => 7
  [6] => 7
  [15] => 6
  [7] => 6
  [20] => 5
  [13] => 3

Your problem is that 3000 / 630 = 4.76 which is far from the average number between 1-20. What we can do is constrain the random numbers' ranges to accommodate this, and get a distribution slant with an average sum approximate to the maximum sum.

Given the required maximum average of 4.76, we can for example generate 1/4 of the random numbers as between 1-20, and 3/4 as between 1-4 to slant the distribution:

function get_slanted_rands() {
        
    $rands = [];
    
    for($i = 1; $i <= 630; $i++) {
        // For every 4th iteration, get random from the full range
        $rands[] = $i % 4 === 0 
            ? mt_rand(1,20)
            : mt_rand(1,4);
    }
    
    $sum = array_sum($rands);
    
    // If the sum is over the max, recall:
    if($sum > 3000) {
        return get_slanted_rands();
    }
    // Log the average for debugging:
    $avg = round($sum / count($rands), 2);
    return compact('sum', 'avg', 'rands');
}

Notice that the function checks the sum and recalls itself on the odd occasion that the sum exceeds 3000. On a typical call, the sum 3000 isn't exceeded with the above "calibration" — since we split 1:3 in favor of the lower range. But random is random, so there's no "average" guaranteed.

Let's test-drive this contraption for 100 iterations and see what we get:

$test = [];
for($t = 1; $t <= 100; $t++) {
    $test[] = get_slanted_rands();
}

$sums = array_column($test, 'sum');
rsort($sums);
echo "==== SUMS ====\n" . implode(', ', $sums) . "\n\n";

$avgs = array_column($test, 'avg');
rsort($avgs);
echo "==== AVGS ====\n" . implode(', ', $avgs);

This yields for the following (reverse sorted), sums between 2600+ and 3000 and averages between 4.75 and 4.19. (On average, ~1:100 iterations exceeds 3000 and is recalled.)

==== SUMS ====
2993, 2985, 2975, 2969, 2959, 2947, 2941, 2933, 2926, 2919, 2919, 2917, 2911, 2909, 2908, 2904, 2903, 2901, 2894, 2894, 2892, 2886, 2884, 2884, 2882, 2881, 2879, 2876, 2871, 2869, 2867, 2863, 2861, 2853, 2852, 2852, 2851, 2851, 2850, 2848, 2844, 2843, 2842, 2838, 2838, 2837, 2837, 2837, 2836, 2834, 2834, 2826, 2826, 2825, 2820, 2814, 2813, 2812, 2802, 2801, 2799, 2799, 2799, 2798, 2796, 2795, 2792, 2789, 2789, 2787, 2784, 2784, 2784, 2783, 2778, 2778, 2776, 2768, 2767, 2764, 2762, 2754, 2754, 2747, 2743, 2737, 2736, 2728, 2727, 2724, 2723, 2721, 2719, 2718, 2707, 2706, 2690, 2673, 2642

==== AVGS ====
4.75, 4.74, 4.72, 4.71, 4.7, 4.68, 4.67, 4.66, 4.64, 4.63, 4.63, 4.63, 4.62, 4.62, 4.62, 4.61, 4.61, 4.6, 4.59, 4.59, 4.59, 4.58, 4.58, 4.58, 4.57, 4.57, 4.57, 4.57, 4.56, 4.55, 4.55, 4.54, 4.54, 4.53, 4.53, 4.53, 4.53, 4.53, 4.52, 4.52, 4.51, 4.51, 4.51, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.5, 4.49, 4.49, 4.48, 4.48, 4.47, 4.47, 4.46, 4.45, 4.45, 4.44, 4.44, 4.44, 4.44, 4.44, 4.44, 4.43, 4.43, 4.43, 4.42, 4.42, 4.42, 4.42, 4.42, 4.41, 4.41, 4.41, 4.39, 4.39, 4.39, 4.38, 4.37, 4.37, 4.36, 4.35, 4.34, 4.34, 4.33, 4.33, 4.32, 4.32, 4.32, 4.32, 4.31, 4.3, 4.3, 4.27, 4.24, 4.19

You can always tweak the slanting condition if you feel it should on average be closer to 3000... Or simply add a recall condition with a "minimum sum" check and "brute force" it. But this suffices to give you the general idea: You need to generate random numbers of a limited range in proportion to what your "average for target sum" demands. Demo at 3v4l: https://3v4l.org/fG74X


Finally, a sample of the sort of distribution you get. Given as "number" => "instances" in a set of 630. It's heavily slanted to 1, 2, 3, 4 there — and that's how it must be to meet your specs!

$nums = get_slanted_rands();
$distribution = array_count_values($nums['rands']);
arsort($distribution);
print_r($distribution);

// yields:
  [3] => 143
  [4] => 125
  [2] => 125
  [1] => 110
  [8] => 13
  [9] => 12
  [18] => 12
  [19] => 10
  [11] => 9
  [5] => 8
  [17] => 8
  [14] => 7
  [12] => 7
  [10] => 7
  [16] => 7
  [6] => 7
  [15] => 6
  [7] => 6
  [20] => 5
  [13] => 3
静赏你的温柔 2025-01-17 01:55:58
$result = [];
$sumCurrent = 0;
$barrier = 3000 / 630;
for ($i = 1; $i <= 630; $i++) {
  $sumBarrier = intval($i * $barrier);
  while (true) {
    $number = random_int(1, 20);
    if ($sumCurrent + $number <= $sumBarrier) {
      break;
    }
  }
  $result[] = $number;
  $sumCurrent += $number;
}

$sum = array_sum($result);

$occurrences = array_count_values($result);
uksort($occurrences, fn($key1, $key2) => $key1 <=> $key2);

print_r($result); echo "\n";
print_r($sum); echo "\n";
print_r($occurrences); echo "\n";
$result = [];
$sumCurrent = 0;
$barrier = 3000 / 630;
for ($i = 1; $i <= 630; $i++) {
  $sumBarrier = intval($i * $barrier);
  while (true) {
    $number = random_int(1, 20);
    if ($sumCurrent + $number <= $sumBarrier) {
      break;
    }
  }
  $result[] = $number;
  $sumCurrent += $number;
}

$sum = array_sum($result);

$occurrences = array_count_values($result);
uksort($occurrences, fn($key1, $key2) => $key1 <=> $key2);

print_r($result); echo "\n";
print_r($sum); echo "\n";
print_r($occurrences); echo "\n";
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文