簡體   English   中英

具有固定總和的隨機整數

[英]Random integer numbers with fixed sum

我正在嘗試創建一個函數,該函數返回一個總和固定的隨機整數數組。

這是我的代碼:

 function arraySum(a) { return a.reduce((a, b) => a + b, 0) } function getRandomIntInclusive(min, max) { const minCeil = Math.ceil(min) const maxFloor = Math.floor(max) return Math.floor(Math.random() * (maxFloor - minCeil + 1)) + minCeil } function randomNumbersWithFixedSum(quantity, sum) { const randoms = [...Array(quantity - 1).keys()].map(q => getRandomIntInclusive(0, sum/quantity)) const last = sum - arraySum(randoms) return [...randoms, last] } console.log(randomNumbersWithFixedSum(1, 100)) console.log(randomNumbersWithFixedSum(2, 100)) console.log(randomNumbersWithFixedSum(3, 100)) console.log(randomNumbersWithFixedSum(4, 100)) console.log(randomNumbersWithFixedSum(5, 100))

它有效,但不完全是我想要的。 我希望每個數字在[0, sum]范圍內都是隨機的。 randomNumbersWithFixedSum函數中,我強制第一個(quantity-1)數字在[0, sum/quantity] ,但我不喜歡。

如何在[0, sum]創建一個真正的隨機數,其總和為sum

這是遞歸函數可以簡化問題的主要示例。 每次執行只計算一個隨機數,然后用更新的參數調用自己。 有關說明,請參閱注釋。

 function getRandomNumberBetweenIncluding(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function randomNumbersWithFixedSum(quantity, sum) { // only a single number required; return the passed sum. if (quantity === 1) { return [sum]; } // Create one random number and return an array containing that number // as first item. Then use the spread operator and recursively execute // the function again with a decremented quantity and the updated // maximum possible sum. const randomNum = getRandomNumberBetweenIncluding(0, sum); return [ randomNum, ...randomNumbersWithFixedSum(quantity - 1, sum - randomNum), ]; } console.log(randomNumbersWithFixedSum(1, 100)); console.log(randomNumbersWithFixedSum(2, 100)); console.log(randomNumbersWithFixedSum(3, 100)); console.log(randomNumbersWithFixedSum(4, 100)); console.log(randomNumbersWithFixedSum(5, 100));

您可以只取最大隨機數的其余部分,然后對數組進行洗牌以僅在數組頂部省略大值

 function shuffle(array) { let i = array.length; while (--i) { let j = Math.floor(Math.random() * (i + 1)), temp = array[j]; array[j] = array[i]; array[i] = temp; } return array; } function getRandomIntInclusive(min, max) { const minCeil = Math.ceil(min) const maxFloor = Math.floor(max) return Math.floor(Math.random() * (maxFloor - minCeil + 1)) + minCeil } function randomNumbersWithFixedSum(length, sum) { length--; const randoms = Array.from({ length }, q => { const r = getRandomIntInclusive(0, sum) sum -= r; return r; }); return shuffle([...randoms, sum]); } console.log(randomNumbersWithFixedSum(5, 100)) console.log(randomNumbersWithFixedSum(4, 100)) console.log(randomNumbersWithFixedSum(3, 100)) console.log(randomNumbersWithFixedSum(2, 100)) console.log(randomNumbersWithFixedSum(1, 100))
 .as-console-wrapper { max-height: 100% !important; top: 0; }

下一個解決方案呢:

  1. 在第一次迭代中,我們嘗試獲得一個介於0max之間的隨機數 - 假設我們檢索N
  2. 在第二次迭代時 - 最大可能值不能大於max - N (否則總和將大於max )。
  3. 繼續quantity - 1步驟。
  4. 在最后一步,我們必須使用剩​​下的直到max

 function getRandomIntInclusive(min, max) { const minCeil = Math.ceil(min) const maxFloor = Math.floor(max) return Math.floor(Math.random() * (maxFloor - minCeil + 1)) + minCeil } function randomNumbersWithFixedSum(quantity, sum) { const result = []; let total = 0; for (let i = 0; i < quantity - 1; i++) { let max = sum - total; let num = getRandomIntInclusive(0, max); result.push(num); total += num; } result.push(sum - total); return result; } console.log(randomNumbersWithFixedSum(1, 100)) console.log(randomNumbersWithFixedSum(2, 100)) console.log(randomNumbersWithFixedSum(3, 100)) console.log(randomNumbersWithFixedSum(4, 100)) console.log(randomNumbersWithFixedSum(5, 100))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM