Random number issue with Next method (.NET Framework) - c#

I need to generate a lot of random numbers which must be anywhere between 1 and int.MaxValue. The arguments passed to the Next method of the Random class are not always the same. In one senario the arguments might be as follows:
Next(1, int.MaxValue);
In another they might as well be:
Next(1, 2);
The issue here is that whenever you pass values like 1 and 2 or 99 and 100, the lower number is always the "random" number returned by the method. The reason for this is because the method subtracts 1 from the maximum value (unless min and max are the same) and then gives you the random number. How would I go about generating a range of random numbers within a range of numbers, as stated above, without getting this predictable outcome?

You would need to pass the inclusive upper bound + 1, ie:
var result = rand.Next(1, 2+1); // Returns 1 or 2
var result2 = rand.Next(99, 101); // Returns 99 or 100
Note that this won't work for int.MaxValue, of course. There is no way to have Random directly return int.MaxValue. To get a [0,int.MaxValue] result, you would need to do:
var result = rand.Next(-1, int.MaxValue) + 1;

The upper bound is exclusive, not inclusive. Given that, the range [1,2) only contains one number, 1, not two.

From the documentation, the first parameter to Next(int, int) is "The inclusive lower bound", while the second is "The exclusive upper bound".
If you want to generate a random number that might be 1 or 2, you should use the following call:
rand.Next(1, 3)

Try this
using System;
namespace ConsoleApplication3
{
class Program
{
static readonly Random r = new Random();
static void Main(string[] args)
{
for (int i = 2; i <= 100; i++)
{
Console.WriteLine(GetRandom(i));
}
}
private static int GetRandom(int i)
{
return 1 + (r.Next(int.MaxValue)%i);
}
}
}
Cheers.

You can get int.MaxValue by adding 1 after getting random int:
var result = rand.Next(1, int.MaxValue) + 1;

How about a method that takes the lower and upper limits and gives you what you're looking for?
Example:
public int GetRandom(int lower, int upper)
{
return upper == int.MaxValue ? rand.Next(lower - 1, upper) + 1 : rand.Next(lower, upper + 1);
}
If the upper limit is int.MaxValue, it shifts the range down by 1 and then adds it back after it gives the random number. Otherwise, it adds 1 to the upper limit and then gives you the random number.
Then when you use it, you'll just do something like:
var randomOne = GetRandom(1, 2);
var randomTwo = GetRandom(99,int.MaxValue);

Related

How to use the length of an integer variable as the termination condition in a for loop

I have a for loop such as:
for (int indexCount = 2, thirdNumber.ToString().Length!=1000; indexCount++)
I want the loop to terminate when there are 1000 digits in thirdNumber. How can I do this?
It's not possible to have an int with 1000 digits. The maximum int value is 2,147,483,647, which is only 10 digits. As far as I'm aware, there are no built-in data types that would represent a number with 1000 digits, or even 100 digits for that matter.
Edit:
A BigInteger can hold an arbitrarily large number (thanks Bradley Uffner). You'll need to add a reference to the System.Numerics assembly. If you use/are using that as your data type, your original comparison of thirdNumber.ToString()!=1000 would be a valid check to see if it is not 1000 digits.
You could also take a more numbers-based approach and compare the BigInteger being checked to the smallest thousand digit number, which is a 1 followed by 999 zeroes. I'm not sure which method would be faster with numbers of this size, though I'd suspect the comparison between two BigIntegers.
class Program
{
static void Main(string[] args)
{
BigInteger minThousandDigits = BigInteger.Parse(new string('9', 999)) + 1;
BigInteger thousandMoreDigits = BigInteger.Parse(new string('5', 1000));
BigInteger notAThousandDigits = BigInteger.Parse(new string('9', 999));
//Displays false
Console.WriteLine($"Is the first number less than a thousand digits? {thousandMoreDigits < minThousandDigits}");
//Displays true
Console.WriteLine($"Is the second number less than a thousand digits? {notAThousandDigits < minThousandDigits}");
Console.ReadLine();
}
}
Use a do loop:
int indexCount = 2;
do
{
// Whatever
indexCount++;
} while (thirdNumber.ToString().Length != 1000);
Note that the loop will always execute at least once in the above example. You can avoid this by using a break statement:
int indexCount = 2;
do
{
if (thirdNumber.ToString().Length == 1000) break;
// Whatever
indexCount++;
} while (true);
The above assumes that length will eventually be equal to 1000, otherwise you'll have an infinite loop.

How to generate random numbers from a range in c# [duplicate]

This question already has answers here:
Produce a random number in a range using C#
(7 answers)
Closed 5 years ago.
So I need to generate random numbers based on user set parameters, and make a basic math expression. They have 3 options; single, double, or triple digit numbers. So based on that I need to generate a random number from 0 to 9, 0 to 99, and 0 to 100.
So far I've read about the Random class. This is my poor attempt:
Random rnd = new Random();
int value = 0;
if (digits == 1)
{
rnd.Next(value);
q1Lbl.Text = value.ToString();
}
You need this overload of Random.Next():
public virtual int Next(
int minValue,
int maxValue
)
Where:
minValue = The inclusive lower bound of the random number returned.
maxValue = The exclusive upper bound of the random number returned.
maxValue must be greater than or equal to minValue.
Note the words inclusive and exclusive in the parameter descriptions. This means the minimum value can be returned in the possible values, while the maximum value will not be possible.
This is further clarified in the description of the return value:
Return Value - A 32-bit signed integer greater than or equal to
minValue and less than maxValue; that is, the range of return values
includes minValue but not maxValue. If minValue equals maxValue,
minValue is returned.
For example, to get single digit values between 0 and 9 (inclusive), you'd use:
int value = rnd.Next(0, 10); // return a value between 0 and 9 inclusive
To get double digits, you'd use:
int value = rnd.Next(10, 100); // return a value between 10 and 99 inclusive
Finally, to get triple digit numbers, you'd use:
int value = rnd.Next(100, 1000); // return a value between 100 and 999 inclusive
Random rnd = new Random();
int single = rnd.Next(1, 10); // 1 ~9
int double = rnd.Next(1, 100); // 1~99
int triple = rnd.Next(1,101); // 1~100
loop it if you want to achieve the values multiple times
There's an overload of the Next method, you only have to pass the range:
Random rnd = new Random();
rnd.Next(1,20); //Gives you a number between 1 and 20
Here you find the entire documentation https://www.google.com.co/search?q=next+random+c%23&oq=next+random&aqs=chrome.1.69i57j0l5.3144j0j7&sourceid=chrome&ie=UTF-8

Random Always Generates The Same Number

I'm using Random class to generate any random integer number but it always returns the same number
static Random rand = new Random();
public static int GetOrderID()
{
return rand.Next(Math.Abs(int.MinValue + 1), int.MaxValue);
}
notice that the random class is static and generated outside the function
What would you expect if
Math.Abs(int.MinValue + 1)
is equal to
int.MaxValue
so your range contains one number only.
It´s simple: Calling Math.Abs will delete the sign from the number. As the minimum integer is -2,147,483,648 its absolute value (incremented by 1) is 2,147,483,647 which equals the absolute value for int.MaxValue.
So when calling Math.Abs(int.MinValue + 1), int.MaxValue you allways get 2,147,483,647as return-value, right?
If you need any arbitrary int you may however use rand.Next(int.MinValue, int.MaxValue) without using Math.Abs. For any non-negative integer-number you can use the overload without any parameters.

How can you separate a string of numbers to single digits using division and the modulo operator?

Lets say someone enter a four digit number 1234 in the console. How can you separate this number in to 1 2 3 4 using only division and the modulo operator?
public static void MathProblem()
{
Console.WriteLine("Type a four digit number:");
//Ex input: 1234
string inputNumber = Console.ReadLine();
// I'm guessing you first need to parse the
// string as an int in some way?
// And then assign it to some variable
// Now, for seperating the digits to be: 1 2 3 4,
// you can (and must) use both division (/), and the remainder (%).
// The first one will be simple, just dividing value with 1000, but
// how about the others? (Remember, % also need to be used at least
// once)
Console.Write("{0},{1},{2},{3}", value/1000, ?, ?, ?;
}
Any guidelines for making this possible for any given four digit input?
Since this seems like a homework problem, I'll simply explain the method in a few steps rather than giving you the code. Having parsed the input as an integer,
A number modulo 10 allows you to obtain its last digit.
Dividing (integer division) the number by 10 removes the last digit.
Repeat while the number is greater than 0.
int num = int.Parse(inputNumber);
Console.Write(string.Format("{0},{1},{2},{3}", (num/1000) % 100, (num/100) % 10, (num/10) % 10, num % 10));
OR
List<int> listOfInts = new List<int>();
while(num > 0)
{
listOfInts.Add(num % 10);
num = num / 10;
}
Console.Write("{0},{1},{2},{3}", listOfInts[3], listOfInts[2], listOfInts[1], listOfInts[0]);
No need to do this by division or modulo operators. Use LINQ. You can get an integer array using LINQ as below:
string inputNumber= "1234"
var intList = inputNumber.Select(digit => int.Parse(digit.ToString()));
Then, you can simply use it as you want like this:
Console.Write("{0},{1},{2},{3}", intList[0]/1000, intList[1], intList[2], intList[3]);
Or simply the way you wanted it using Division and Modulo Operator:
public int[] ParseIntString(int number)
{
List<int> digits= new List<int>();
while(number> 0)
{
digits.Add(number% 10);
number= number/ 10;
}
digits.Reverse();
return digits.ToArray();
}
I hope this helps you
int[] values;
Seperate(inputNumber, out values);
Console.Write("{0},{1},{2},{3}", values[0] / 1000, values[1], values[2], values[3]);
Console.ReadKey();
}
public static void Seperate(string numbers, out int[] values)
{
values = new int[numbers.Length];
for (int x = 0; x <= numbers.Length - 1; x++)
{
values[x] = int.Parse(numbers[x].ToString());
}
}
I just started a course in coding and had this as homework as well. I did it in excel first because I thought it was easier than running code over and over and it's more a math problem than a coding one.
Say the number is 4352.
The first digit is easy, it's the integer of the number / 1000 = 4.
Then you simply multilpy by 1000 to get 4000. Remove that and you get 352. The integer of that / 100 is 3.
Then you times that by 100 to get 300 and remove that and you get 52, the integer of that / 10 is 5. Multiply that by 10 and remove that and you're left with 2.
Just read that you must use % so I suggest getting the last number as a modular of 10

Selecting a number from natural number < n excluding a possibility

Given n natural number starts from 0, and b which is a number in between 0 to n
I wish to randomly select a number excluding b.
Say n is 5
then The number to be selected is {0,1,2,3,4,5}
say b is 4,
then my random selection is from {0,1,2,3,5}
A way to do this is to do a while loop, until the random.nextInteger() does not find a 4.
Is there a easy to to do this other than using a while loop?
I would write a simple extension:
// N.B. : min is inclusive, max is exclusive; so range is: [min,max) - {toExclude}
public static int Next(this Random rand, int min, int max, int toExclude)
{
int v = rand.Next(min, max - 1);
if (v < toExclude)
return v;
return v + 1;
}
Usage:
var random = new Random();
var val = random.Next(0,6,4); // 6 because max is exclusive in C# random.Next()
Your approach is the best in my optinion. It is simple and elegant, and even for m=2 it is O(1) on average (The expected number of redraws is 1/2 + 1/4 + 1/8 + .... < 1).
If you want to avoid the worst case of infinite loop there is an alternative, though I doubt it will have real performance impact.
draw a random double in range [0,1]. let it be d. If d < b/m: draw a number in range [0,b) and return it.
Else (d > b/m) - draw a random number in range [b+1,m] and return it.
Note, it is indeed uniform distributed because:
There are m+1 numbers in range 0,...,m, but only m "valid" numbers (excluding b).
There are b numbers in range 0,1,...,b-1 - so the probability of the number being in this range assuming uniform distribution is b/m - which is exactly P(d < b/m).
In java it will look similar to this:
int m = 5, b = 4;
Random r = new Random();
double d = r.nextDouble();
if (d < ((double)b)/m) {
System.out.println(r.nextInt(b));
} else {
System.out.println(r.nextInt(m-b) + b + 1);
}
Here is another approach if you prefer:
import random
def random_unifrom(n,b):
assert b < n and n > 0 and b > 0
nMinusOneList = [i for i in range(n) if i != b]
lSize = len(nMinusOneList)
randIndex = random.randint(0, lSize-1)
return nMinusOneList[randIndex]
I wrote this in python just for simplicity.
creating the nMinusOneList has complexity of O(n).
returning the random index complexity depends on the random function you are using.
At the end, you loose nothing if you take this approach instead of a while loop, but even if you use the while loop approach, if the random function is random (!!) then you should not have a problem. However, my approach above excludes the number you do not need from the very beginning.
In C#, the one line I use in python might be a couple of lines which consists of a for loop on the range 0 to n, with a condition that the x (for loop index) does not equal to b, in building the list, and then you will have the list that excludes b.

Categories

Resources