簡體   English   中英

隨機小數導致負數

[英]Random decimal leads to negative

我正在嘗試獲取一個貨幣值(使用decimal ),然后將其分成分布在14個不同標簽中的隨機部分,這些標簽加起來就是原始值。

示例:值50.00

  • 1 = 1.50
  • 2 = 3.50
  • 3 = 7.00
  • 4 = .75
  • 5 = 1.25
  • 6 = 2.00
  • 7 = 5.50
  • 8 = 6.10
  • 9 = 0.60
  • 10 = .50
  • 11 = 5.30
  • 12 = 3.00
  • 13 = 3.00
  • 14 = 10.00

(不是精確的值,而是類似的隨機值,它們將總計為總計)

問題是我不知道以下幾點:

  1. 第一個隨機數較高(如果該值為50,則第一個數字通常為40),而其余數字則小於5
  2. 其次,輸出數字不是十進制格式-它們都是整數
  3. 最后,一半數字為正數,一半數字為負數。 它的確等於我想要的數量,但我不希望出現負輸出。

我正在使用的代碼:

 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.

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