Get `n` random values between 2 numbers having average `x`

前端 未结 5 641
你的背包
你的背包 2021-01-28 12:21

I want to get n random numbers(e.g n=16)(whole numbers) between 1 to 5(including both) so that average is x.

x can be any value between (1, 1.5, 2, 2.5, 3,

5条回答
  •  长情又很酷
    2021-01-28 12:49

    I have written the JS implementation for this:

    function getRandom(min, max) {
      return Math.random() * (max - min) + min;
    }
    function getArr(size, avg, min, max) {
      let arr = [];
      let tmax = max;
      let tmin = min;
      while (arr.length < size) {
        const variable1 = +getRandom(min, tmax).toFixed(1);
        let variable2 = +(avg * 2 - variable1).toFixed(1);
        if (variable2 < min) {
          tmax = max - (min - variable2);
          variable2 = min;
        } else if (variable2 > max) {
          tmin = min + (variable2 - max);
          variable2 = max;
        } else {
          tmax = max;
          tmin = min;
        }
        arr = arr.concat([variable1, variable2]);
      }
      let sumErr = arr.reduce((a, b) => a + b, 0) - avg * size;
      if (sumErr > 0) {
        arr = arr.map((x) => {
          if (x > min && sumErr > 0.001) {
            let maxReduce = x - min;
            if (maxReduce > sumErr) {
              const toReturn = +(x - sumErr).toFixed(1);
              sumErr = 0;
              return toReturn;
            } else {
              sumErr -= maxReduce;
              return min;
            }
          }
          return x;
        });
      } else {
        arr = arr.map((x) => {
          if (x < max && sumErr < -0.001) {
            let maxAdd = max - x;
            if (maxAdd > Math.abs(sumErr)) {
              const toReturn = +(x + Math.abs(sumErr)).toFixed(1);
              sumErr = 0;
              return toReturn;
            } else {
              sumErr += maxAdd;
              return max;
            }
          }
          return x;
        });
      }
    
      return arr.sort(() => Math.random() - 0.5);
    }
    
    const output = getArr(40, 2.01, 0.5, 2.5)
    const outputAvg = output.reduce((a, b) => a + b, 0) / 40
    console.log(`givenAvg: ${2.01} outputAvg: ${outputAvg}`)
    console.log(output)

提交回复
热议问题