[英]Random decimal leads to negative
我正在嘗試獲取一個貨幣值(使用decimal
),然后將其分成分布在14個不同標簽中的隨機部分,這些標簽加起來就是原始值。
示例:值50.00
(不是精確的值,而是類似的隨機值,它們將總計為總計)
問題是我不知道以下幾點:
我正在使用的代碼:
private void generatewins(Decimal amount)
{
Decimal initialValue = amount;
Decimal currentRemainder = amount;
var values = new List<int>();
Label[] labels = { win1, win5, win10, win9, win6, win2, win3, win7, win8, win11, win13, win12, win4 };
Random rnd = new Random();
Decimal remainingPortion = initialValue;
for (int i = 0; i < 13; i++)
{
Decimal val = currentRemainder - rnd.Next(14 - i);
currentRemainder -= val;
labels[i].Text = Convert.ToString(val) + "";
win14.Text = currentRemainder.ToString();
}
}
為了澄清一些事情,我使用標簽的原因是我必須將這些標簽放置在表單上的特定位置,以便它們會隨着表單大小和表單上另一個對象的變化而改變。 我認為使用標簽會更容易。 同樣,數字14也不是其余部分; 它被設置為從初始值中減去剩余值,因為當我將其添加到隨機拆分的值中時,它將始終顯示為0,而其他13個值將不等於初始值。
好,從問題2開始,它們是整數的原因是因為您的隨機結果將是整數。 使用rnd.NextDouble()代替,它將獲得一個介於0和1之間的隨機十進制數。
聽起來好像是一個不好的范圍,但對於解決問題1)有益,結果開始時很大,然后又變小。 這顯然是因為您提供的隨機范圍會隨着循環的進行而變化和縮小。 我要做的就是簡單地循環14次(或任何循環),並獲得0和1之間的14個隨機數。然后! 將所有數字相加,然后將總和除以總值(在您的情況下為50.00),然后再次遍歷,然后將所有數字乘以結果。 這將使這些數字相加,從而使所有數字都有相等的機會成為范圍內的任何數字
decimal Total = 50.00;
decimal randTotal = 0;
decimal []values = new decimal[14];
for(int i = 0; i<14; i++)
{
values[i] = rnd.NextDouble();
randTotal += values[i]
}
decimal co = Total / randTotal;
for (int i = 0; i < 14; i++)
values[i] *= co;
值將是一個隨機十進制數字的數組,這些總數加起來就是Total。
然后,如果您想對舍入進行舍入(精確到最接近的一分),我將執行以下操作:
decimal leftOver = 0;
for(int i = 0; i<14; i++)
{
decimal centFraction = values[i] - Math.floor(values[i] * 100) / 100; //floor rounds a number down to the nearest whole number
values[i]-=centFraction;
leftOver+=centFraction;
}
//then just add the left over cents (which should be in whole cents!) to one of them
values[0]+=leftOver;
這可能不是最好的方法,因為從技術上講,這意味着現在沒有平均分配,但是可能呢?
PS問題3是由於您僅根據與總數無關的范圍獲得14個隨機數而引起的。 如果您的總數是2美元,您可以清楚地看到您對rnd.Next(14-i)的第一次調用(獲得0到14之間的隨機數)很容易導致數字大於2。
我想你需要像這樣的循環
decimal Total = 50.00M;
for ( i = 0; i <= 14; i++)
{
Random random = new Random();
decimal newDec = Math.Round((random.NextDouble(0 , Total) / 100),3));
//do something to log newDec
Total -= newDec;
}
Random類返回整數。 如果需要十進制數字,可以除以100。
還要注意,Next的參數是隨機數的大小。 您應該將其限制為所需數量的大小。 這就是為什么您得到負數的原因-如果返回的隨機數大於當前余數((14-i)最終大於當前余數的情況可能會發生,那么該值將為負數。
隨着第一個數字的增加,請考慮第一個迭代的可能結果。 隨機數介於0到14之間,因此val結果必須始終比原始數小14。 您真正想要的是一個偏斜的分布,其中第一個val可以是零到原始值之間的任何值,但要取平均值(CurrentRemainder /(14-i))。 這將給出更多隨機值。 要知道可以確保正確隨機數的最佳分布,需要比我更多的數學專家,但是要保證每次迭代都在零到當前余數的范圍內,那么至少您不會超過總數。 一個簡單的解決方案是將值限制在平均值的0到兩倍之間,像這樣...
十進制currentRemainder = initialValue;
for (int i = 0; i < 13; i++)
{
Decimal avg = (currentRemainder/(14-i));
Decimal val = currentRemainder - (rnd.Next(avg*2*100)/100);
currentRemainder -= val;
labels[i].Text = Convert.ToString(val) + "";
win14.Text = currentRemainder.ToString();
}
labels[13] = Convert.ToString(currentRemainder);
那應該很接近了。 要獲得完全理想的隨機分布,將需要更多的數學知識來調整每個值,這超出了我的范圍。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.