Re: [問題] 平均的亂數產生數字個數 C++[新問題]
請不要在問題獲得回答之後,
卻把原文的問題敘述給修掉,
感覺這種作法,
像是把這邊的版友們當作是"呼之則來,揮之則去"、"利用完就可以丟的免洗筷"。
也讓之前沒有參與討論的人,
沒辦法知道當初問題是什麼,
回答的內容是回答什麼樣的問題,
同時就失去當初本版規定不得自刪文章的用意了。
如果我沒有記錯的話,
當初的這一項規定是為了讓後面的人可以爬文,
尋找自己可能的類似問題,來找到過去的解法,
不然之後的人,常常問到以前有人提出的問題,
有常在這個版看文章的人,
一定會看到有的問題根本會經常性的出現。
以上是個人感想的廢話。
///////////////////////////////////////////////////////////////////////////////
如果是要每種數字出現次數均相同的話,
在 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
05/03 14:08, 1F
→
05/03 14:09, , 2F
05/03 14:09, 2F
→
05/03 14:10, , 3F
05/03 14:10, 3F
→
05/03 14:11, , 4F
05/03 14:11, 4F
→
05/03 14:12, , 5F
05/03 14:12, 5F
→
05/03 14:12, , 6F
05/03 14:12, 6F
推
05/03 16:20, , 7F
05/03 16:20, 7F
討論串 (同標題文章)