Random.Next() never returning the number 0

MegasXLR

Member
Joined
Nov 3, 2018
Messages
5
Location
Sofia, Bulgaria
Programming Experience
Beginner
Hello everyone,

I'm kind of new to C# in general (only made a few console apps around two years ago) and am making a Random Number Generator app for Windows. Everything works perfectly except one thing:
Whenever I enter 0 as the lower bound and tick the checkbox to include it (so the result can contain a 0 as well) the whole program crashes for some reason. I tested the function in a seperate console app by doing:
C#:
Random random = new Random();
Console.WriteLine(random.Next(0, 2));
The above code should print either 0 or 1 and indeed it does print both numbers (one at a time and randomly ofcourse) so why does my Forms app not like it when I include 0?
I'm attaching my app here. Any help is appreciated :)
 

Attachments

  • RandomNumbersGenerator.zip
    14.7 KB · Views: 43
Last edited by a moderator:

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,210
Location
Sydney, Australia
Programming Experience
10+
It would be easier to look at the relevant code in this thread and see where the problem is than downloading, extracting and opening your project. If we can't work it out from there then we can always ask for the whole project. It is sometimes required but rarely, thus it should not be the first option. The first option should be the relevant code, so...
 

MegasXLR

Member
Joined
Nov 3, 2018
Messages
5
Location
Sofia, Bulgaria
Programming Experience
Beginner
So here's the function that generates the numbers:
        private void generateRandomNumbers(object sender, EventArgs e)
        {
            if ((this.numbersAmountInputBox.Text != null) && (this.rangeFromInputBox.Text != null) && (this.rangeToInputBox.Text != null))
            {
                bool amountNumsIsOK = Int32.TryParse(this.numbersAmountInputBox.Text, out int amountNums);
                bool fromNumIsOK = Int32.TryParse(this.rangeFromInputBox.Text, out int fromNum);
                bool toNumIsOK = Int32.TryParse(this.rangeToInputBox.Text, out int toNum);


                this.resultBox.Clear();


                if ((amountNumsIsOK) && (fromNumIsOK) && (toNumIsOK))
                {
                    amountNumsGlobal = amountNums;


                    int[] array = new int[amountNums];
                    Random random = new Random();
                    int temp = 0;
                    int min = 0;
                    int max = 0;


                    if ((this.includeFromCheckBox.Checked) && (this.includeToCheckBox.Checked))
                    {
                        min = fromNum;
                        max = toNum + 1;
                    }
                    else if ((this.includeFromCheckBox.Checked) && (!this.includeToCheckBox.Checked))
                    {
                        min = fromNum;
                        max = toNum;
                    }
                    else if ((!this.includeFromCheckBox.Checked) && (this.includeToCheckBox.Checked))
                    {
                        min = fromNum + 1;
                        max = toNum + 1;
                    }
                    else if ((!this.includeFromCheckBox.Checked) && (!this.includeToCheckBox.Checked))
                    {
                        min = fromNum + 1;
                        max = toNum;
                    }


                    if (min >= max)
                    {
                        this.resultBox.Clear();
                        this.resultBox.Text += "Please make sure that the borders are set correctly: From < To!";
                    }
                    else if ((min < max) && (max - min < amountNums))
                    {
                        this.resultBox.Clear();
                        this.resultBox.Text += "Please make sure that there are enough numbers inside the borders: To - From >= Amount!";
                    }
                    else if ((min < max) && (max - min >= amountNums))
                    {
                        if (this.resultTypeComboBox.SelectedIndex == 0)
                        {
                            for (int i = 0; i < array.Length; i++)
                            {
                                temp = random.Next(min, max);
                                while (isDuplicate(temp, array))
                                {
                                    temp = random.Next(min, max);
                                }
                                array[i] = temp;
                            }
                        }
                        else if (this.resultTypeComboBox.SelectedIndex == 1)
                        {
                            for (int i = 0; i < array.Length; i++)
                            {
                                temp = random.Next(min, max);
                                while (isDuplicate(temp, array))
                                {
                                    temp = random.Next(min, max);
                                }
                                array[i] = temp;
                            }
                            Array.Sort(array);
                        }
                        else if (this.resultTypeComboBox.SelectedIndex == 2)
                        {
                            for (int i = 0; i < array.Length; i++)
                            {
                                temp = random.Next(min, max);
                                while (isDuplicate(temp, array))
                                {
                                    temp = random.Next(min, max);
                                }
                                array[i] = temp;
                            }
                            Array.Sort(array);
                            Array.Reverse(array);
                        }


                        for (int i = 0; i < array.Length; i++)
                        {
                            this.resultBox.Text += array[i] + " ";
                        }


                        defaultArray = new int[amountNumsGlobal];
                        string values = this.resultBox.Text;
                        string[] tokens = values.Split(' ');


                        for (int i = 0; i < tokens.Length - 1; i++)
                        {
                            defaultArray[i] = Int32.Parse(tokens[i]);
                        }
                    }
                }
                else
                {
                    this.resultBox.Clear();
                    this.resultBox.Text += "Please enter only whole positive integer numbers in all blank input spaces!";
                }


                generateButtonPressed = true;
            }
        }

The checkboxes if-else statements are for including/excluding the lower/upper bounds in the result so I guess that's where my problem would be at.
Whenever I enter 0 as the lower bound and tick the checkbox to include it (so the result can contain a 0 as well) and set the borders to exactly the amount of available numbers including zero the whole program crashes for some reason.

Example:
Amount of nums to generate: 2
Lower bound inclusive: 0
Upper bound inclusive: 1
Result: Crash (Not Responding), while it should show me a result containing the numbers 0 and 1 in it (0 1 or 1 0, duplicates not allowed).

If I make it like this:
Amount of nums to generate: 2
Lower bound inclusive: 0
Upper bound inclusive: 2
The result always contains the numbers 1 and 2 but NEVER the number 0, although it is included and should show up from time to time (as the generation is random, but when I spam the generate button it must show at least once).

Weird thing is that when I do in a seperate console app the above test with the 0 and 1 inclusive it does show 0, so the problem isn't in the Random.Next() function. What's wrong? :(
 
Last edited:

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,210
Location
Sydney, Australia
Programming Experience
10+
Have you actually debugged that code, i.e. set a breakpoint and stepped through it line by line, examining the state at each step? If you're saying that it crashes under certain circumstances when it should do something else seems to suggest not. You should do that now. At the very least, you can explain to us exactly where the actual state differs from your expectations and what data is in use at the time, but you should be able to do more than that. If you don't know how to debug, start learning here:

https://msdn.microsoft.com/en-us/library/y740d9d3.aspx?f=255&MSPPError=-2147217396

As well as debugging, you need to learn how to write test code. I said earlier that you should post the RELEVANT code and there's far more than that there. Stack Overflow makes a recommendation that you post a Minimal, Complete & Verifiable Example and you should do that here and everywhere else too. What that means is to strip out everything that isn't directly relevant tot he issue. You should be doing that for yourself first though. That means putting your project aside and creating new test project with the simplest possible code to test the specific functionality you are having issues with. The simpler the code is, the easier it is to narrow down exactly where the issue is. If things work as expected, add one more feature. Continue in that vein until things break. You then know that the last change you made is at least partly responsible for the issue so you have inherently narrowed it down considerably.

The way to not go about things is to write all your code, run it and then post the lot on public forums and wait for it to be fixed. There's a lot more to software development than writing and reading code. Debugging and testing is where you spend most of your time, if you consider design part of software engineering rather than development.
 

MegasXLR

Member
Joined
Nov 3, 2018
Messages
5
Location
Sofia, Bulgaria
Programming Experience
Beginner
I used a MessageBox.Show() on each step where problem might have been and sure enough I found out what it was :)
Sadly an empty array created with "int[] array = new int[number]" is filled with zeros in C#, not null. I think in C++ it wasn't like that, but could be wrong. And I have a check for duplicates in the array:
C#:
for (int i = 0; i < array.Length; i++)                            {
      temp = random.Next(min, max);
       while (isDuplicate(temp, array))
        {
               temp = random.Next(min, max);
        }
        array[i] = temp;
}
So it turns out that when I enter and include 0 in the input it gets stuck in this loop forever as all values of the array are 0. Is there a way to make the array truly empty (aka not have any zeros in it after initialization)?

Since my RNG works between 0 and 99 I can always just make all values of the array have value 100 after its initialization and then everything would work perfectly but I'd rather do it the right way if possible.
 
Last edited:
Top Bottom