Re: [問題] 平均的亂數產生數字個數 C++[新問題]

看板C_and_CPP作者 (非天夜翔)時間13年前 (2012/05/03 06:04), 編輯推噓1(106)
留言7則, 2人參與, 最新討論串3/7 (看更多)
請不要在問題獲得回答之後, 卻把原文的問題敘述給修掉, 感覺這種作法, 像是把這邊的版友們當作是"呼之則來,揮之則去"、"利用完就可以丟的免洗筷"。 也讓之前沒有參與討論的人, 沒辦法知道當初問題是什麼, 回答的內容是回答什麼樣的問題, 同時就失去當初本版規定不得自刪文章的用意了。 如果我沒有記錯的話, 當初的這一項規定是為了讓後面的人可以爬文, 尋找自己可能的類似問題,來找到過去的解法, 不然之後的人,常常問到以前有人提出的問題, 有常在這個版看文章的人, 一定會看到有的問題根本會經常性的出現。 以上是個人感想的廢話。 /////////////////////////////////////////////////////////////////////////////// 如果是要每種數字出現次數均相同的話, 在 cofficent != 1 時,是不可能出現的。 下面只是其中一種解法,`讓出現次數盡可能為一個等差數列' int genSize = 400; double cofficent = 0.9; double NumSet = { 3,9,11,33}; // 假定數字為遞增的集合 const int SetSize = 4; double orgAvg = 14; // averege(NumSet,SetSize) double newAvg = 12.6; // orgAvg * cofficent int newFreq[SetSize]; int tmpFreq[SetSize]; double tmpSet[SetSize]; /////////////////////////////////////////////////////////////////////////////// // 做到每種數字出現頻率為一個等差數列 // /////////////////////////////////////////////////////////////////////////////// int i,j; for(i = 0 , j = SetSize - 1; i < SetSize ; ++i , j = j - 2) { tmpSet[i] = orgAvg - NumSet[i]; tmpFreq[i] = j; } double tmpMult = 0.0; for(i = 0 ; i < SetSize ; ++i) { tmpMult += tmpSet[i] * tempFreq[i]; } double baseFreq = (double)genSize / SetSize; double k = (orgAvg - newAvg) * tmpMult; for(i = 0 ; i < SetSize ; ++i) { newFreq[i] = (int)(baseFreq + tmpFreq[i] * k); } 由於上面的 k, baseFreq 可能會是小數, 所以在轉回整數型態會有誤差, 以下這段是將各種數字出現次數總和調整為 genSize, 故調整的是讓真正平均值最接近平均值(newAvg)的數字所出現的次數。 int m = genSize; double sum = genSize * newAvg; for(i = 0 ; i < SetSize ; ++i) { m -= newFreq[i]; sum -= newFreq[i] * NumSet[i]; } if(m != 0) { int index = 0; double sumDivM = sum / m; double diff = abs(NumSet[index] - sumDivM); for(i = 1 ; i < SetSize ; ++i) { test = abs(NumSet[i] - sumDivM); if( diff > test ) { index = i; diff = test; } } } newFreq[index] += m; ※ 引述《csihcs (非天夜翔)》之銘言: : 先問個問題,來做個初步了解, : 在紙上操作的時候, : 當有 {4, 5, 9, 10} 四種數字可以產生 : 可產生的數字平均值為 (4+5+9+10)/4 = 7 : 設定倍數為 0.9 : 設定產生數量為 100 : 你是希望 : (1) 產生的所有亂數平均為 7*0.9 = 6.3 : (2)-1 每一種數字只能最多有 100/4 = 25 個 : (2)-2 每一種數字恰有 100/4 = 25 個 : A : (1) 成立 : B : (2)-? 成立 : C : (1) 和 (2)-? 都成立 : 還是其它種需求 : 說真的我看完你的描述, : 實在難以理解你的需求。 : 請先以紙上操作的方式, : 來說明你所期望的目標。 : ------------------------------------------------------------------------------- : 首先不考慮如何產生亂數這部分如何實做, : 請先給予幾個範例說明你期待達成的目標, : 不然實在很難給你想法來實作所提的內容。 : /////////////////////////////////////////////////////////////////////////////// : 當在 {4, 5, 9, 10} 這個亂數可用範圍, : 第一部分: : 當所乘的倍數為 1, : 產生 200 個亂數。 : 你所期望的螢幕顯是的樣子為何? : 一、限定產生數字總個數 200 個(genSize),每種數字 各 (200/4 = 50) 個, : 出現順序隨機 : 如: 4,4,5,5,5,5,10,10,5,5,9,9,9,9,9,9, ..... : 共計 4 有 50 個 : 5 有 50 個 : 9 有 50 個 : 10 有 50 個 : 總平均為 7,總個數 200 個 : 二、限定產生數字總個數 200 個(genSize),不限定 每種數字可用的個數, : 出現順序隨機 : 如:(A) : 4,10,4,4,10,4,10,10,10,10,..... : 共計 4 有100 個 : 10 有100 個 : 總平均為 7,總個數為 200 個 : (B) : 5,5,5,5,5,5,9,9,9,9,9,5,9,5,9,... : 共計 5 有100 個 : 9 有100 個 : 總平均為 7,總個數為 200 個 : (C) : 4,5,10,5,9,9,5,5,5,10,9,9,9,10,4,4,4,5,5,10,10,10,.... : 共計 4 有 85 個 : 5 有 15 個 : 9 有 15 個 : 10 有 85 個 : 總平均為 7,總個數為 200 個 : (A)(B)(C)任一種均可行 : 三、不限定產生數字總個數(genSize),限定 每種數字 個數相同,出現順序隨機 : 四、不限定產生數字總個數(genSize),不限定 每種數字 個數是否相同,出現順序隨機 : 五、或者是其他類型的需求 : ******************************************************************************* : 第二部分: : 當所乘的倍數為 0.9, : 產生 200 個亂數, : 你所期望的螢幕顯示的樣子為何? : 一、限定產生數字總個數 200 個(genSize),不限定 每種數字可用的個數, : 出現順序隨機 : 如:(A) : 4,10,4,4,10,4,10,10,5,5,10,10,5,5..... : 共計 4 有120 個 : 5 有 4 個 : 10 有 76 個 : 總平均為 6.3,總個數為 200 個 : (B) : 5,5,10,10,5,4,5,10,5,5,4,4,4,4,4,5,4,5,4,10,10... : 共計 4 有100 個 : 5 有 28 個 : 10 有 72 個 : 總平均為 6.3,總個數為 200 個 : (C) : 4,5,10,5,5,5,9,5,10,9,9,9,10,4,4,9,9,4,5,5,10,10,10,.... : 共計 4 有100 個 : 5 有 26 個 : 9 有 10 個 : 10 有 64 個 : 總平均為 6.3,總個數為 200 個 : (A)(B)(C)任一種均可行 : 二、或是其他種類型的需求 : ------------------------------------------------------------------------------- : 但是就原文所表達的,我的理解如下: : 並沒有提到每種數字要一樣多這回事, : 只要輸出的數字平均為 6.3 就好。 : 但是以文後補充的部分, : 卻又必須要達成其他特定條件"不能超過", : 也說明的很模糊, : 原文本來只有提到亂數可用數字為 {1,2,3} 共計 3 種數字 : 為什麼要不能超過 (100 / 4 = 25),而不是 (100 / 3 = 33.333) : 100 所要除的 `4' 這個數字到底哪來的。 : ------------------------------------------------------------------------------- : int SetSize; // 可出現數的集合數量 ex: 4 : int NumSet[SetSize]; // 數字集合 ex:{4,5,9,10} : double orgAvg = averege(NumSet,SetSize); // 原始平均數 ex: 7 : double cofficent; // 設定倍數 ex: 0.9 : double newAvg = orgAvg * cofficent; // 需求平均數 ex: 6.3 : int genSize; // 產生數的數量 ex: 200 : ------------------------------------------------------------------------------- : ※ 引述《bernachom (Terry)》之銘言: : 開發平台(Platform): (Ex: VC++, GCC, Linux, ...) : VC++ : 問題(Question): : 請教一下 : 我先說明一下我的問題 : 我現在有3個數字亂數產生 : 最少產生1個,最多產生3個 : EX: 1+rand()%(3); : 然後我平均亂數產生的數字要是這三個數字的平均 : 也就是說 : 1+rand()%(3); 可能產生的數字有1,2,3 : 平均就是(1+2+3)/3 = 2 : 那我平均亂數產生的數字長期平均下來要是2 : 然後這個平均可能會是變動的 : 例如說,我可能會乘上0.9, 0.8, 0.7...之類的 : 假如(1+2+3)/3 = 2,我乘上0.8之後,變成了1.6 : 那我產生的亂數長期平均下來也要是1.6 : 不知道各位前輩有沒有什麼想法 : 我目前沒有辦法做到這個樣子 : 只能做到 : 我不用亂數產生 : 我每次的輸入都是2 : 然後如果要滿足1.6的話 ex:「(1+2+3)/3 = 2,我乘上0.8之後,變成了1.6」 : 就是用亂數機率的方法,有10分之6的機率會是2,另外10分之4的機率會是1 : 例如產生出來可能會是這個樣子: : 2 2 2 2 2 2 1 1 1 1 : 這樣子平均就是1.6了 : 但是這也只是兩個數字2和1的組合而已 : 不知道如果用3個數字要如何達成... : 希望前輩們提供一些想法 : 如果有說明不清楚的地方我再補充 : 謝謝 : == : 方法有想到了,我先測試看看 : 到時後再說明 -- 渴望飛翔在自由中, 期望逃離這拘束的現實, 一切都讓他隨著而去, 獨自躲在黑暗空氣中, 舔舐被狠狠撕裂的傷口。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 1.164.92.116

05/03 14:08, , 1F
說不可能出現的理由是{3,9,11,33} 分別出現 100 次,平均仍
05/03 14:08, 1F

05/03 14:09, , 2F
然會是 14,你要改變獲得的平均值不是14的話,必須改變各種
05/03 14:09, 2F

05/03 14:10, , 3F
數字所佔的比例,當然 newAvg 必須介在 min(NumSet) 與
05/03 14:10, 3F

05/03 14:11, , 4F
max(NumSet) 之間。
05/03 14:11, 4F

05/03 14:12, , 5F
也就是你要 newAvg != orgAvg 的話,就達不到各種數字比例
05/03 14:12, 5F

05/03 14:12, , 6F
相同。
05/03 14:12, 6F

05/03 16:20, , 7F
push :)
05/03 16:20, 7F
文章代碼(AID): #1FeX_Nin (C_and_CPP)
討論串 (同標題文章)
本文引述了以下文章的的內容:
以下文章回應了本文
完整討論串 (本文為第 3 之 7 篇):
文章代碼(AID): #1FeX_Nin (C_and_CPP)