【问题标题】:JavaScript - generating 6 random percentages that add up to 100JavaScript - 生成 6 个随机百分比,加起来为 100
【发布时间】:2013-09-10 19:27:25
【问题描述】:

我希望在 JavaScript 中生成 6 个随机百分比,它们的总和为 100。我不希望最大百分比和最小百分比之间的差异超过 20%。

最有效的方法是什么?

非常感谢。

【问题讨论】:

  • 仅整数?是否允许零作为值?它们必须是唯一的还是可以重复?
  • 最好只使用整数。不允许零作为值。允许重复。抱歉我没说清楚。

标签: javascript random numbers percentage


【解决方案1】:

我遇到了类似的问题。这样做的一个好处是,不仅数字是随机的,而且数组最大的项目也是随机的,因为数组已经被打乱了。

否则,大多数情况下第一个数字将是最大的,第二个数字将是第二个最大的等等。

另一个好处是,这将生成任意数量的细分,并且您可以对最大细分设置一个上限。例如如果你想加到 100,你的第一个数字不会是 99.9。

var generateProportion = function() {
  var max = 100,
    segmentMax = 60,
    tempResults = [],
    remaining = max,
    segments = 5,
    finalResults = [];

   //create a series of random numbers and push them into an array
  for (var i = 1; i <= segments; i++) {
    var r = Math.random() * segmentMax;
    if (i === segments) {
      // the final segment is just what's left after the other randoms are added up
      r = remaining;
    }
    tempResults.push(r);
    // subtract them from the total
    remaining -= r;
    // no segment can be larger than what's remaining
    segmentMax = remaining;
  }

  //randomly shuffle the array into a new array
  while (tempResults.length > 0) {
    var index = Math.floor(Math.random() * tempResults.length);
    finalResults = finalResults.concat(tempResults.splice(index, 1));
  }
  return finalResults;
}
var proportion = generateProportion();
var total = proportion.reduce( (a,b) => a+b);
console.log(proportion, "=", total);
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"&gt;&lt;/script&gt;

【讨论】:

    【解决方案2】:

    这是部分解决方案:

    function get_6_rands() {
        var rands = [], rand, total = 0, normalized_rands = [];
        for (var i = 0; i < 6; i += 1) {
            rand = Math.random();
            rands.push(rand);
            total += rand;
        }
        for (var i = 0; i < 6; i += 1) {
            rand = rands[i] / total;
            normalized_rands.push(rand);
        }
        return normalized_rands;
    }
    
    function_is_valid(attempt) {
        return true; // implement `is_valid` yourself
    }
    do {
        var attempt = get_6_rands();
    } while (is_valid(attempt) === false);
    console.log(attempt); // success!
    

    该函数将生成 6 个随机数,它们加起来是 1。它是通过标准化来实现的。如果你想要整数(而不是浮点数),你需要做一些聪明的事情,仅仅四舍五入是不够的。

    您可以通过检查要求获得20% 要求,如果失败,请重试,并继续尝试,直到获得满足您要求的要求。你最终应该得到一个,毕竟它是随机的。

    【讨论】:

      【解决方案3】:

      首先,您制作一个 100 到 120 之间的随机数数组,如下所示:

      var arPercentages = [];
      
      for(var i = 0; i < 6; i++) {
          arPercentages.push(Math.random()*20 + 100);
      }
      

      然后将所有数字相加。选择你的方法,我总是使用下划线,所以我会 map()。但基本上,你要做的就是这样:

      var total = arPercentages[0] + arPercentages[1] + arPercentages[2] + arPercentages[3] + arPercentages[4] + arPercentages[5];
      

      最后你只需要对每个数字进行除法和乘法:

      for (var i = 0; i < 6; i++) {
          arPercentages[i] = arPercentages[i] / total * 100;
      }
      

      您有一个包含 6 个百分比的数组,加到 100 并且介于基值的 100% 到 120% 之间(但这非常接近)

      【讨论】:

      • 当我运行这段代码时,数字总是在 15 到 18 之间。我认为你误解了 20% 的规则。我认为像 16,16,16,16,8,28 这样的结果是允许的,因为 28-8 = 20。
      • 正确。允许两个值之间有 20% 的差异,但这将是最大值,或者有一种设置方法。
      【解决方案4】:

      我不得不解决一个类似的问题。我就是这样做的:

      const random = (min, max) => {
          return min + Math.random() * (max - min);
      };
      
      const randomFill = (amount, min, max) => {
          const arr = [];
          let total = 0;
      
          // fill an array with random numbers
          for (let i = 0; i < amount; i++) arr.push(random(min, max));
      
          // add up all the numbers
          for (let i = 0; i < amount; i++) total += arr[i];
      
          // normalise so numbers add up to 1
          for (let i = 0; i < amount; i++) arr[i] /= total;
      
          return arr;
      };
      

      minmax 可以是任何东西。实际值并不重要,因为总数是标准化的。

      const values = randomFill(6, 0.2, 0.5);
      // [0.1549, 0.2023, 0.1681, 0.0981, 0.1621, 0.2141]
      

      这是一个 jsfiddle:https://jsfiddle.net/brunoimbrizi/q3fLp8u5/27/

      【讨论】:

        猜你喜欢
        • 2021-03-22
        • 2018-06-23
        • 2014-08-17
        • 2012-06-24
        • 1970-01-01
        • 1970-01-01
        • 2021-06-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多