【问题标题】:Generating random values and keeping track of their sum生成随机值并跟踪它们的总和
【发布时间】:2013-05-30 02:18:31
【问题描述】:

我在数据库表中有超过 200 个条目,我想为每个条目生成一个随机值,但最后,条目值的总和必须等于 100。是否可以使用 for 循环来做到这一点和 rand() 在 PHP 中?

【问题讨论】:

  • 总和怎么能小于总行数,您是否允许零值?您还为每行随机值设置了一个范围,就好像您允许 0-100 一样,第一行可能会得到 100,而其余行则归零……您是否暗示了为什么或为什么需要这个随机数…… .
  • 是的,只要确保你的随机数是整数 >= 1
  • 您可以计算所有值,然后将该数字除以 100。然后在 0.1 和该结果之间随机化一个值并分配给每个条目。总和将始终低于 100。您知道您的数字将是浮点数(即不是整数)吗?
  • 您需要详细说明您到底想要什么,因为就目前而言,您的问题有点荒谬。现在,有 200 行并且要求总和小于 100,您只能可靠地使用 (float)(rand()/getrandmax())*0.5; 或 mySQL RAND() * 0.5
  • @silkfire,数字当然是浮点数。

标签: php random for-loop


【解决方案1】:

您可以简单地将一组数字标准化,例如:

$numbers = array();
for ($i = 0; $i < 200; $i += 1) {
  $numbers[] = rand();
}

$sum = array_sum($numbers);

// divide $sum by the target sum, to have an instant result, e.g.:
// $sum = array_sum($numbers) / 100;
// $sum = array_sum($numbers) / 42;
// ...

$numbers = array_map(function ($n) use($sum) {
  return $n / $sum;
}, $numbers);

print_r($numbers);
print_r(array_sum($numbers)); // ~ 1

演示:http://codepad.viper-7.com/RDOIvX

【讨论】:

  • 我承认这比我建议的要整洁。
  • @Yoshi,但是如何将总和设为 100 而不是 ~ 1? :)
  • @Psyche 只需在标准化后将每个值乘以 100(或目标总和应该是什么)。
  • @Psyche 乘以 100 怎么样? =)
  • @Psyche ... 或将$sum 除以目标总和。这真的取决于你。 ;)
【解决方案2】:

您的问题的解决方案是将数字从 0 到 200,然后放入数组中,然后对这些值求和,然后除以 200。循环遍历元素并将每个元素除以先前等式的结果,它会给你答案

$sum = 0;
$max = 100; //max value to be sumed
$nr_of_records = 200; // number of records that should sum to $max
$arr = array();
for($i=0;$i<$nr_of_records;++$i)
{
   $arr[$i] = rand(0,$max);
}

$div = array_sum($arr) / $max;


for($i=0;$i<$nr_of_records;++$i)
{
  $arr[$i] /= $div;
  echo $arr[$i].'<br>';
}

echo array_sum($arr);

Created living example

【讨论】:

  • 嗯,总和必须是 100,而不是 200,即使有 200 个元素。
【解决方案3】:

100 到底有多精确?只是好奇,因为所有提示都以使用浮点值结束,这往往是不准确的。

我建议使用分数...假设 10000 个分数,每个分数为 1/100 点(10000 * 1/100 = 100 点)。使用整数将 10000 个点分配给 200 个元素 - 并且绝对确定,所有整数除以 10000 的总和为 100。不需要浮点数,只需考虑拐角处...

【讨论】:

    【解决方案4】:

    做多/少一点:

    $size = 200;
    $sum = 100;
    $places = 3;
    
    $base = round($sum/$size, $places);
    
    $values = array_fill(0, $size, $base);
    
    for($i=0; $i<$size; $i+=2) {
        $diff = round((rand()/getrandmax()) * $base, $places);
        $values[$i]   += $diff;
        $values[$i+1] -= $diff;
    }
    
    //optional: array_shuffle($values);
    
    $sum = 0;
    
    foreach($values as $item) {
        printf("%0.3f ", $item);
        $sum += $item;
    }
    
    echo $sum;
    

    输出:

    0.650 0.350 0.649 0.351 0.911 0.089 0.678 0.322 0.566 0.434 0.563 0.437 0.933 0.067 0.505 0.495 0.503 0.497 0.752 0.248 0.957 0.043 0.856 0.144 0.977 0.023 0.863 0.137 0.766 0.234 0.653 0.347 0.770 0.230 0.888 0.112 0.637 0.363 0.716 0.284 0.891 0.109 0.549 0.451 0.629 0.371 0.501 0.499 0.652 0.348 0.729 0.271 0.957 0.043 0.769 0.231 0.767 0.233 0.513 0.487 0.647 0.353 0.612 0.388 0.509 0.491 0.925 0.075 0.797 0.203 0.799 0.201 0.588 0.412 0.788 0.212 0.693 0.307 0.688 0.312 0.847 0.153 0.903 0.097 0.843 0.157 0.801 0.199 0.538 0.462 0.954 0.046 0.541 0.459 0.893 0.107 0.592 0.408 0.913 0.087 0.711 0.289 0.679 0.321 0.816 0.184 0.781 0.219 0.632 0.368 0.839 0.161 0.568 0.432 0.914 0.086 0.991 0.009 0.979 0.021 0.666 0.334 0.678 0.322 0.705 0.295 0.683 0.317 0.869 0.131 0.837 0.163 0.792 0.208 0.618 0.382 0.606 0.394 0.574 0.426 0.927 0.073 0.661 0.339 0.986 0.014 0.759 0.241 0.547 0.453 0.804 0.196 0.681 0.319 0.960 0.040 0.708 0.292 0.558 0.442 0.605 0.395 0.986 0.014 0.621 0.379 0 .992 0.008 0.622 0.378 0.937 0.063 0.884 0.116 0.840 0.160 0.607 0.393 0.765 0.235 0.632 0.368 0.898 0.102 0.946 0.054 0.794 0.206 0.561 0.439 0.801 0.199 0.770 0.681 0.319 0.794 0.681 0.319 0.794 0.681 0.319 0.794 0.681 0.319 0.794 0.681 0.319 0.794 0.206 100

    如果您不使用 100 和 200 之类的好数字,则舍入会变得有点模糊,但不会超过 0.1。

    【讨论】:

    • 好招!在这个用例中不太可能,但在密码学中,数字之间的任何相关性都会产生负面影响。
    • @Szocske 你总是可以运行几百/千次迭代,包括随机播放,但我敢打赌,无论它们多么随机,让 X 加起来为 Y 的数字在加密中本质上是无用的。 :P
    【解决方案5】:

    昨天的原始问题正好有 200 个条目,总和“不超过 100”。 我昨天的原始答案:

    确保使用不大于 0.5 的随机数。

    或者,取决于这些数字需要多么“随机”(如何 允许很大的相关性),你可以保持一个运行总数,如果 它变得不成比例地高,你可以混合一堆更小的 价值观。

    编辑:

    改变问题的方式,让我看起来很愚蠢并被否决。

    要获得准确的总和,您必须进行归一化,最好使用精确分数而不是浮点数以避免舍入错误。

    【讨论】:

    • 这不会导致总和等于 100
    • @Dragon:昨天的问题不是这个。
    猜你喜欢
    • 2012-03-19
    • 1970-01-01
    • 2018-09-19
    • 2022-06-06
    • 2011-04-05
    • 2020-07-16
    • 2017-04-17
    • 1970-01-01
    • 2020-08-29
    相关资源
    最近更新 更多