Świat liczb pseudolosowych

0

Witam,

Z nudów i z ciekawości zacząłem pisać program do analizowania liczb losowych oraz liczb wylosowanych w grze Lotto.
Na początku skupiłem się na generowaniu liczb pseudolosowych w C# i analizowania wyników.

Pierwszy podstawowy test to oczywiście ilość wypadnięć danej liczby w świetle wszystkich losowań.
Zrobiłem pierwszy test - 500 tysięcy losowań... i zdziwiłem się. Spodziewałem się wyników równomiernie rozłożonych. W rezultacie osiągnąłem taki oto wynik:

Liczba 1 wylosowana została 141404 razy. Procent: 28,2808%
Liczba 2 wylosowana została 140471 razy. Procent: 28,0942%
Liczba 3 wylosowana została 139442 razy. Procent: 27,8884%
Liczba 4 wylosowana została 139094 razy. Procent: 27,8188%
Liczba 5 wylosowana została 139571 razy. Procent: 27,9142%
Liczba 6 wylosowana została 138831 razy. Procent: 27,7662%
Liczba 7 wylosowana została 138793 razy. Procent: 27,7586%
Liczba 8 wylosowana została 137627 razy. Procent: 27,5254%
Liczba 9 wylosowana została 137215 razy. Procent: 27,443%
Liczba 10 wylosowana została 136781 razy. Procent: 27,3562%
Liczba 11 wylosowana została 136712 razy. Procent: 27,3424%
Liczba 12 wylosowana została 135734 razy. Procent: 27,1468%
Liczba 13 wylosowana została 135398 razy. Procent: 27,0796%
Liczba 14 wylosowana została 135204 razy. Procent: 27,0408%
Liczba 15 wylosowana została 134530 razy. Procent: 26,906%
Liczba 16 wylosowana została 134305 razy. Procent: 26,861%
Liczba 17 wylosowana została 134765 razy. Procent: 26,953%
Liczba 18 wylosowana została 133481 razy. Procent: 26,6962%
Liczba 19 wylosowana została 133494 razy. Procent: 26,6988%
Liczba 20 wylosowana została 132398 razy. Procent: 26,4796%
Liczba 21 wylosowana została 132128 razy. Procent: 26,4256%
Liczba 22 wylosowana została 132176 razy. Procent: 26,4352%
Liczba 23 wylosowana została 131723 razy. Procent: 26,3446%
Liczba 24 wylosowana została 131242 razy. Procent: 26,2484%
Liczba 25 wylosowana została 130863 razy. Procent: 26,1726%
Liczba 26 wylosowana została 129823 razy. Procent: 25,9646%
Liczba 27 wylosowana została 129588 razy. Procent: 25,9176%
Liczba 28 wylosowana została 129728 razy. Procent: 25,9456%
Liczba 29 wylosowana została 129276 razy. Procent: 25,8552%
Liczba 30 wylosowana została 127909 razy. Procent: 25,5818%
Liczba 31 wylosowana została 127955 razy. Procent: 25,591%
Liczba 32 wylosowana została 127869 razy. Procent: 25,5738%
Liczba 33 wylosowana została 127760 razy. Procent: 25,552%
Liczba 34 wylosowana została 126849 razy. Procent: 25,3698%
Liczba 35 wylosowana została 126121 razy. Procent: 25,2242%
Liczba 36 wylosowana została 126235 razy. Procent: 25,247%
Liczba 37 wylosowana została 125541 razy. Procent: 25,1082%
Liczba 38 wylosowana została 125186 razy. Procent: 25,0372%
Liczba 39 wylosowana została 124942 razy. Procent: 24,9884%
Liczba 40 wylosowana została 124153 razy. Procent: 24,8306%
Liczba 41 wylosowana została 124566 razy. Procent: 24,9132%
Liczba 42 wylosowana została 123595 razy. Procent: 24,719%
Liczba 43 wylosowana została 123485 razy. Procent: 24,697%
Liczba 44 wylosowana została 123111 razy. Procent: 24,6222%
Liczba 45 wylosowana została 122667 razy. Procent: 24,5334%
Liczba 46 wylosowana została 122482 razy. Procent: 24,4964%
Liczba 47 wylosowana została 121707 razy. Procent: 24,3414%
Liczba 48 wylosowana została 121618 razy. Procent: 24,3236%
Liczba 49 wylosowana została 121358 razy. Procent: 24,2716%
Liczba 50 wylosowana została 120983 razy. Procent: 24,1966%
Liczba 51 wylosowana została 120580 razy. Procent: 24,116%
Liczba 52 wylosowana została 120200 razy. Procent: 24,04%
Liczba 53 wylosowana została 119923 razy. Procent: 23,9846%
Liczba 54 wylosowana została 119610 razy. Procent: 23,922%
Liczba 55 wylosowana została 119328 razy. Procent: 23,8656%
Liczba 56 wylosowana została 119221 razy. Procent: 23,8442%
Liczba 57 wylosowana została 118587 razy. Procent: 23,7174%
Liczba 58 wylosowana została 117993 razy. Procent: 23,5986%
Liczba 59 wylosowana została 118177 razy. Procent: 23,6354%
Liczba 60 wylosowana została 117478 razy. Procent: 23,4956%
Liczba 61 wylosowana została 117436 razy. Procent: 23,4872%
Liczba 62 wylosowana została 116982 razy. Procent: 23,3964%
Liczba 63 wylosowana została 116547 razy. Procent: 23,3094%
Liczba 64 wylosowana została 116274 razy. Procent: 23,2548%
Liczba 65 wylosowana została 115702 razy. Procent: 23,1404%
Liczba 66 wylosowana została 115704 razy. Procent: 23,1408%
Liczba 67 wylosowana została 114550 razy. Procent: 22,91%
Liczba 68 wylosowana została 115058 razy. Procent: 23,0116%
Liczba 69 wylosowana została 114740 razy. Procent: 22,948%
Liczba 70 wylosowana została 114091 razy. Procent: 22,8182%
Liczba 71 wylosowana została 114269 razy. Procent: 22,8538%
Liczba 72 wylosowana została 113114 razy. Procent: 22,6228%
Liczba 73 wylosowana została 113113 razy. Procent: 22,6226%
Liczba 74 wylosowana została 112901 razy. Procent: 22,5802%
Liczba 75 wylosowana została 113168 razy. Procent: 22,6336%
Liczba 76 wylosowana została 112136 razy. Procent: 22,4272%
Liczba 77 wylosowana została 112216 razy. Procent: 22,4432%
Liczba 78 wylosowana została 111376 razy. Procent: 22,2752%
Liczba 79 wylosowana została 111017 razy. Procent: 22,2034%
Liczba 80 wylosowana została 110620 razy. Procent: 22,124%

Jest to dosyć zaskakujący wynik, gdyż według mnie wyniki powinny być rozłożone równomiernie po każdych liczbach (około 25% dla każdej). Pierwsze założenie: błąd w kodzie.

Zacząłem szukać i zauważyłem (co nie było trudne), że wyniki są PRAWIE posortowane (widać powyżej, że liczba 1 wypadała najczęściej a 80 najmniej razy). Podczas wyświetlania wyników Lotto sortuje sobie liczby by łatwiej je było czytać i analizować.
Problem w tym, że to sortowanie nie ma nic wspólnego z powyższymi wynikami (posortowane liczby to losowania, a tutaj tylko ilość wypadnięć danych liczb).
Mimo to wyłączyłem losowanie i uzyskałem wynik poprawny - czyli liczby równomiernie rozłożone.

Jednak... według mnie błędu w kodzie nie ma. Mam podejrzenie, że to randomizer C# zachowuje się dziwnie.

Oto kawałek kodu formatki:

private void MultiLotekMake()
        {
            this.SetStatus("Trwa losowanie...");
            StringBuilder builder = new StringBuilder();
            this.ProgressRandomizer.Maximum = (int)this.NumbersRandomBox.Value;

            for (int i = 0; i < this.NumbersRandomBox.Value; i++)
            {
                this.multiLotek.MakeLotto();
                builder.AppendLine("Numer losowania: " + (i+1).ToString() + "  -  " + this.multiLotek.GetNumbersLottoInString());
                this.ProgressRandomizer.Value++;
            }

            this.SetStatus("Trwa wyświetlanie wyników...");
            this.tbRandomNumbers.Text = builder.ToString();
            this.tbCountNumbers.Text = this.multiLotek.GetCountNumbersInString((int)this.NumbersRandomBox.Value);
            this.ProgressRandomizer.Value = 0;
            this.SetStatus(DONE);
        }

        private void btnMultiLotek_Click(object sender, EventArgs e)
        {
            try
            {
                this.MultiLotekMake();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

Oto fragment kodu losowania:

private int GetNewNumber()
{
int randomNumber = 0;
do
{
randomNumber = this.rand.Next(1, this.maxNumbersInLotto);
} while (this.IsNumberInList(randomNumber));
return randomNumber;
}

    public void MakeLotto()
    {
        for (int i = 0; i < this.numbers.Length; i++)
        {
            int numberRandom = this.GetNewNumber();
            this.numbers[i] = numberRandom;
            this.stats.SetAddToNumbers(numberRandom);
        }
        Array.Sort(this.numbers);
    }

Prosze zwrócić uwagę na linię:

Array.Sort(this.numbers);

wyłączenie tego sortowania ukazuje poprawne wyniki, ale...

Oto kod statystyk:

public class Stats
    {
        private int[] numbers;

        public Stats(int maxNumber)
        {
            this.numbers = new int[maxNumber];
            HelperMethods.ZeroArray(this.numbers);
        }

        public string GetCountNumbersInString(int countRandom)
        {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < this.numbers.Length; i++)
                builder.AppendLine("Liczba " + (i+1).ToString() + " wylosowana została " + this.numbers[i] + " razy." +
                    " Procent: " + ((this.numbers[i] * 100.0) / countRandom).ToString() + "%");
            return builder.ToString();
        }

        public void SetAddToNumbers(int number)
        {
            number--;
            this.numbers[number]++;
        }

Czy ktoś widzi może tutaj błąd w kodzie, który powodowałby błędne losowania liczb?
Z sorotwaniem: Array.Sort(this.numbers);
wyniki są "dziwne", natomiast gdy wyłączę to sortowanie to wyniki wydają się być poprawne.
Problem w tym, że owo sortowanie wykonuję na sam koniec losowania i nie ma ono wpływu na nic.

Czy to jest dziwne zachowanie randomizera C#?

Pozdrawiam.

0

Poradziłem sobie z problemem, ale nadal nie wiem z czego on wynika.

Wiecie co zrobiłem?
Zamieniłem tablicę, na listę w module z losowaniem.

Ale dlaczego powyższy kod generuje takie liczby? To jest ciekawe.

1 użytkowników online, w tym zalogowanych: 0, gości: 1