Generating random numbers with yield changes its values during debug mode - c#

I had a complex scenario when I was using a yield with random numbers and faced some strange behavior.
I tried to simplify my case with a simpler code example and managed to reproduce it with a very simple code.
In the following code, I would expect to get "Equal!" printed, but actually, it is not.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleAppSample
{
static class Program
{
public static void Main(string[] args)
{
IEnumerable<int> randomNumbers = GetRandomNumbers();
int firstRandomnumber = randomNumbers.First();
if (firstRandomnumber == randomNumbers.First())
{
Console.WriteLine("Equal!");
}
}
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
lock (syncLock)
{
return random.Next(min, max);
}
}
private static IEnumerable<int> GetRandomNumbers(int loopCount = 2)
{
for (int i = 0; i < loopCount; i++)
{
yield return RandomNumber(int.MinValue, int.MaxValue);
}
}
}
}
I tried to debug it and found even something weirder. While holding the breakpoint at the same place the values of the randomNumbers variable change every moment.
In the following image, you can see the watch shows different numbers for the same variable.
If I change the GetRandomNumbers() method implementation to insert values into a list and return the list (without using yield), it will work fine.
I try to understand why it works this way? I guess it is related to the way random generates numbers based on the computer clock and the way yield works, but I am not sure.

yield means that the collection is not saved but essentially calculated when needed, namely each time you iterate the collection. Thus, each time new Random().Next() is called which may or may not give you a different result, depending on the time between those calls.
Thus, I would suggest the following changes:
If you want to see the same collection contents everytime, save the collection (for example, into a List as you suggested)
If you want to have multiple random numbers, keep the Random instance, if necessary in a static field. Creating a new instance will calculate a new seed based on the current system time and that may be the same, if you create two instances before Windows refreshes the system time.

Related

Functionally pure dice rolls in C#

I am writing a dice-based game in C#. I want all of my game-logic to be pure, so I have devised a dice-roll generator like this:
public static IEnumerable<int> CreateDiceStream(int seed)
{
var random = new Random(seed);
while (true)
{
yield return 1 + random.Next(5);
}
}
Now I can use this in my game logic:
var playerRolls = players.Zip(diceRolls, (player, roll) => Tuple.Create(player, roll));
The problem is that the next time I take from diceRolls I want to skip the rolls that I have already taken:
var secondPlayerRolls = players.Zip(
diceRolls.Skip(playerRolls.Count()),
(player, roll) => Tuple.Create(player, roll));
This is already quite ugly and error prone. It doesn't scale well as the code becomes more complex.
It also means that I have to be careful when using a dice roll sequence between functions:
var x = DoSomeGameLogic(diceRolls);
var nextRoll = diceRolls.Skip(x.NumberOfDiceRollsUsed).First();
Is there a good design pattern that I should be using here?
Note that it is important that my functions remain pure due to syncronisation and play-back requirements.
This question is not about correctly initializing System.Random. Please read what I have written, and leave a comment if it is unclear.
That's a very nice puzzle.
Since manipulating diceRolls's state is out of the question (otherwise, we'd have those sync and replaying issues you mentioned), we need an operation which returns both (a) the values to be consumed and (b) a new diceRolls enumerable which starts after the consumed items.
My suggestion would be to use the return value for (a) and an out parameter for (b):
static IEnumerable<int> Consume(this IEnumerable<int> rolls, int count, out IEnumerable<int> remainder)
{
remainder = rolls.Skip(count);
return rolls.Take(count);
}
Usage:
var firstRolls = diceRolls.Consume(players.Count(), out diceRolls);
var secondRolls = diceRolls.Consume(players.Count(), out diceRolls);
DoSomeGameLogic would use Consume internally and return the remaining rolls. Thus, it would need to be called as follows:
var x = DoSomeGameLogic(diceRolls, out diceRolls);
// or
var x = DoSomeGameLogic(ref diceRolls);
// or
x = DoSomeGameLogic(diceRolls);
diceRolls = x.RemainingDiceRolls;
The "classic" way to implement pure random generators is to use a specialized form of a state monad (more explanation here), which wraps the carrying around of the current state of the generator. So, instead of implementing (note that my C# is quite rusty, so please consider this as pseudocode):
Int Next() {
nextState, nextValue = NextRandom(globalState);
globalState = nextState;
return nextValue;
}
you define something like this:
class Random<T> {
private Func<Int, Tuple<Int, T>> transition;
private Tuple<Int, Int> NextRandom(Int state) { ... whatever, see below ... }
public static Random<A> Unit<A>(A a) {
return new Random<A>(s => Tuple(s, a));
}
public static Random<Int> GetRandom() {
return new Random<Int>(s => nextRandom(s));
}
public Random<U> SelectMany(Func<T, Random<U>> f) {
return new Random(s => {
nextS, a = this.transition(s);
return f(a).transition(nextS);
}
}
public T Run(Int seed) {
return this.transition(seed);
}
}
Which should be usable with LINQ, if I did everything right:
// player1 = bla, player2 = blub, ...
Random<Tuple<Player, Int>> playerOneRoll = from roll in GetRandom()
select Tuple(player1, roll);
Random<Tuple<Player, Int>> playerTwoRoll = from roll in GetRandom()
select Tuple(player2, roll);
Random<List<Tuple<Player, Int>>> randomRolls = from t1 in playerOneRoll
from t2 in playerTwoRoll
select List(t1, t2);
var actualRolls = randomRolls.Run(234324);
etc., possibly using some combinators. The trick here is to represent the whole "random action" parametrized by the current input state; but this is also the problem, since you'd need a good implementation of NextRandom.
It would be nice if you could just reuse the internals of the .NET Random implementation, but as it seems, you cannot access its internal state. However, I'm sure there are enough sufficiently good PRNG state functions around on the internet (this one looks good; you might have to change the state type).
Another disadvantage of monads is that once you start working in them (ie, construct things in Random), you need to "carry that though" the whole control flow, up to the top level, at which you should call Run once and for all. This is something one needs to get use to, and is more tedious in C# than functional languages optimized for such things.

List C# capacity is always 0 even though using a constructor with capacity ?

Given this simple synchronization code :
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Mutex
{
class CalcArrayThreads
{
private static System.Threading.Mutex mutex = new System.Threading.Mutex();
private const int ThreadsNumber = 10;
private static List<int> list = new List<int>(10);
public static void SumPartialArray(object index)
{
mutex.WaitOne();
int indexBoxed = (int) index;
int sum = 0;
for (int i = indexBoxed; i < indexBoxed + 9; i++)
{
sum += i;
}
Console.WriteLine(string.Format("Thread : {0} Calculated value : {1}", Thread.CurrentThread.Name, sum));
// list.Add(sum);
list[indexBoxed] = sum;
mutex.ReleaseMutex();
// Console.WriteLine(list.Count());
}
static void Main(string[] args)
{
for (int i = 0; i < ThreadsNumber; i++)
{
Thread myThread = new Thread(new ParameterizedThreadStart(SumPartialArray));
myThread.Name = String.Format("Thread{0}", i + 1);
myThread.Start(i);
}
Console.Read();
}
}
}
When I use the line :
list[indexBoxed] = sum;
I get :
Unhandled Exception: System.ArgumentOutOfRangeException: Index was out
of range. Must be non-negative and less than the size of the
collection.
Even though the capacity of the list is 10 .
Why ?
If you just did the following with an array, it'd work as expected, setting the second element:
int[] list = new int[10];
list[2] = 5; // second element is 5, no exception thrown
Looking at the List<T> constructor, when you pass in a capacity, it's actually doing something very similar using an internal array:
this._items = new T[capacity];
So it seems like it should work then, when you try to access any element less than capacity, but here's how the indexer is implemented:
public T this[int index]
{
get
{
if (index >= this._size)
throw new ArgumentOutOfRangeException("...");
return this._items[index];
}
set
{
if (index >= this._size)
throw new ArgumentOutOfRangeException("...");
this._items[index] = value;
}
}
It's actually checking a _size variable first, and throwing the exception if the index you're requesting is larger than it. If it weren't for that check, it'd work as you expect.
_size is initialized to 0 unless you pass a non-empty collection into the constructor, and changes value when you use the Add, RemoveAt, Clear, etc methods. Internally, it's still just using an array to store the elements, and if _size is greater than the capacity (say, after trying to Add one more element), it allocates a new array and copies all the elements from the older (smaller) array into it.
I see two solutions you could consider using:
Either just use an array, like this:
private static int[] list = new int[10];
Or supply a collection of some default value (here, a bunch of zeroes) via the constructor:
private static List<int> list = new List<int>(Enumerable.Repeat(0, 10));
Since you have not added anything to the list yet. It will always be 0.
You actually need to use Count property to get the number of elements in the list.
A remark from MSDN:
Capacity is the number of elements that the List can store before
resizing is required, whereas Count is the number of elements that are
actually in the List.
Capacity is always greater than or equal to Count. If Count exceeds
Capacity while adding elements, the capacity is increased by
automatically reallocating the internal array before copying the old
elements and adding the new elements.
The value you are passing in the constructor is the initial capacity which then is increased dynamically as the list grows.
But the list is still empty. And using the index accessor on an empty list will yield the exact exception you are seeing.
To add elements to the list use Add method instead and don't worry about the capacity. It grows internally.
EDIT: As to the title of your question, I belive that the Count is allways 0 (you are not adding elements to it) and not the Capacity.

Using clock ticks as random number seed

I'm using the current clock ticks as a seed for random number generation. The random number is used in a pseudo GUID and a check in my database will make sure it doesn't already exist before returning. On average, this method will be called around 10k times in succession during the life of the process.
My concern is that an identical number might be generated back to back resulting in multiple unnecessary recursive calls to my database checking for the same ID. I'd like to avoid this if possible. What is the best way to test this scenario?
If it matters, application is .NET 4 and database is SQL Server 2008.
private static string GenerateUniqueDelId()
{
// Generate a random integer using the current number of clock ticks as seed.
// Then prefix number with "DEL" and date, finally padding random integer with leading zeros for a fixed 25-character total length.
int seed = (int)DateTime.Now.Ticks;
Random number = new Random(seed);
string id = string.Format("DEL{0}{1}", DateTime.Today.ToString("yyyyMMdd"), number.Next().ToString("D14"));
// Lookup record with generated ID in Sesame. If one exists, call method recursively.
string query = "SELECT * FROM Lead WHERE Esm_Id = #Esm_Id";
SqlParameter[] parameters = { new SqlParameter("#Esm_Id", id) };
if (DataManager.GetRow(query, parameters, DelConnection.Sesame) != null) return GenerateUniqueDelId();
// Otherwise, return ID.
return id;
} //// End GenerateUniqueDelId()
You are right in your concern: You should move the creation of your Random instance out of your method body - otherwise you will re-seed with the same value many times which results in the same number sequence.
Also you are kinda re-inventing the wheel: the default constructor of the Random class already uses the current clock time as default seed.
The question is why don't you avoid all of this and just use an auto-generated Guid on the database side?
Quoting Jon Skeet
When you see the word "random" in a question title on Stack Overflow you can almost guarantee it will be the same fundamental problem as countless similar questions. This article takes a look at why randomness causes so many problems, and how to address them.
Check his article about random number generators
http://csharpindepth.com/Articles/Chapter12/Random.aspx
basically his solution looks like:
using System;
using System.Threading;
public static class RandomProvider
{
private static int seed = Environment.TickCount;
private static ThreadLocal<Random> randomWrapper = new ThreadLocal<Random>(() =>
new Random(Interlocked.Increment(ref seed))
);
public static Random GetThreadRandom()
{
return randomWrapper.Value;
}
}

Returning number sequence in an optimised, thread safe manner

I'm looking for some advice on writing some thread safe, optimized, elegant code to do the following:
I want a static method to return a sequence of integers. So for example, the application starts, thread 1 calls the GetSequence method and says it wants to take 3, so it gets an integer array back consisting of 0,1,2. Thread 2 then calls the method and says give me 4, so it returns 3,4,5,6. Multiple threads can simultaneously call this method.
To give an idea of the sort of thing I'm thinking of, here's my attempt at this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SequenceNumberService
{
class Program
{
static void Main(string[] args)
{
int[] numbers = NumberSequenceService.GetSequence(3);
foreach (var item in numbers)
{
Console.WriteLine(item.ToString());
}
// Writes out:
// 0
// 1
// 2
Console.ReadLine();
}
}
public static class NumberSequenceService
{
private static int m_LastNumber;
private static object m_Lock = new Object();
public static int[] GetSequence(int take)
{
int[] returnVal = new int[take];
int lastNumber;
// Increment the last audit number, based on the take value.
// It is here where I am concerned that there is a threading issue, as multiple threads
// may hit these lines of code at the same time. Should I just put a lock around these two lines
// of code, or is there a nicer way to achieve this.
lock (m_Lock)
{
m_LastNumber = m_LastNumber + take;
lastNumber = m_LastNumber;
}
for (int i = take; i > 0; i--)
{
returnVal[take - i] = lastNumber - i;
}
return returnVal;
}
}
}
My questions therefore are:
Am I approaching this in the best way, or is there another way to achieve this?
Any suggestions for optimizing this code?
Many thanks in advance for any help.
You probably want to look into the Interlocked class and it's Increment and Add methods:
public static Int32 num = 0;
public static Int32 GetSequence()
{
return Interlocked.Increment(ref num);
}
public static IEnumerable<Int32> GetSequenceRange(Int32 count)
{
var newValue = Interlocked.Add(ref num, count);
return Enumerable.Range(newValue - count, count);
}

Random not working

To clarify, multiple students objects and all of them are getting the same value.
I know this question has been asked before, but I have had no luck with the other posts about his topic. I have a random number generator ranging from 1-3. I then us %2 to make a bool value true or false. Every time I run the program I either get all true or all false. Here is my code. I know that random is not really random. What can I do to get more random numbers.
Random random = new Random();
public Student()
{
int randomLevel=random.Next(1,3);
level = (randomLevel % 2 == 0);
}
public bool readingLevel()//this always returns one value for the entire program.
{
return level;
}
You are only assigning a random value to 'level' once during the constructor, so it will always have the initial value.
Try:
public bool readingLevel()
{
return (random.Next(1,3) % 2 == 0);
}
Edit:
Static Random random = new Random();
...
It looks like you're trying to get a random number!
Clippy
Well you can try something like this:
static Random random = new Random();
public Student()
{
lock (random)
{
int randomLevel=random.Next(1,3);
level = (randomLevel % 2 == 0);
}
}
public bool readingLevel()//this always returns one value for the entire program.
{
return level;
}
The problem with your snippet seems to be that you are instantiating a new Random class with each of your class instances.
This is not the way Random is supposed to be used, but instead a single Random class instance should be used for acquiring multiple random numbers.
The Rationale for this is that Random in .Net uses a pseudo random algorithm based on state (a seed) that changes every time you ask for a new random number. By instantiating multiple random classes in a relatively short time span, there is a high chance that all of them will be initiated with the same seed (Based on system time) and all will give the same random number.
It looks like your random generator is an instance variable of the Student. Since the generator uses the current time as the seed, if you create a bunch of students within a short time, they will all have each have a generator with the same seed and the same results. You could make the random generator a static variable or, better yet, use constructor injection and pass the level into the Student's constructor.
class Student
{
private static Random random = new Random();
public Student()
{
level = random.NextDouble() < 0.5;
}
public bool readingLevel()
{
return level;
}
}
or use constructor injection so your student class is deterministic.
class Student
{
private boolean level;
public Student(boolean readingLevel)
{
this.level = readingLevel;
}
public boolean readingLevel()
{
return level;
}
}
Create only one instance of Random and reuse it. Creating multiple instances of random in quick succession seeds to the same value and thus leads to the same sequence.
If your code in single threaded you can simply use a static property to hold the instance of Random.
The default seed value is derived from the system clock and has finite resolution. As a result, different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers. This problem can be avoided by using a single Random object to generate all random numbers. You can also work around it by modifying the seed value returned by the system clock and then explicitly providing this new seed value to the Random(Int32) constructor. For more information, see the Random(Int32) constructor.
http://msdn.microsoft.com/en-us/library/h343ddh9.aspx
public Student()
{
int randomLevel=random.Next(1,3);
level = (randomLevel % 2 == 0);
}
seems very much like a constructor for the Student class. In this constructor you are basically calculating a random number and storing it inside the level field. So if you use the same instance of Student throughout your entire program and call the readingLevel() method multiple times on this instance it will obviously return the same value -> the one that was done during the construction of this instance and that you stored in the level field.
So you might consider moving the random number generation logic into the readingLevel() method instead of simply returning the same value over and over again:
public class Student
{
private Random random = new Random();
public bool readingLevel()
{
int randomLevel = random.Next(1,3);
return (randomLevel % 2 == 0);
}
}
Now everytime you call this method on the same instance you should get a new calculation of a random number.
Some others have said this, but I think the point deserves underscoring with an example.
public class Student
{
Random random = new Random();
public Student()
{
int randomLevel=random.Next(1,3);
level = (randomLevel % 2 == 0);
}
public bool readingLevel()//this always returns one value for the entire program.
{
return level;
}
}
public class Program
{
public static void Main()
{
var students = new List<Student>();
for (int i = 0; i < 10; i++)
students.Add(new Student());
//Now you have 10 Students; each Student has its own random number generator
//The generators were created within microseconds of each other, so they most likely have THE SAME SEED
//Because they have the same seed, they will generate identical sequences of numbers
//Each student's reading level is calculated from the first call to .Next(1, 3) on its own RNG.
//The RNGs have the same seed, so each will return the same value for the first call to .Next(1, 3)
//Therefore, all students will have the same reading level!
}
}
You are using random to simulate a true/false situation, so you are trying to limit the result to either 1 or 2. Given that you are doing an odd/even test on the result you might be better off doing:
int randomLevel = random.Next();
level = (randomLevel % 2 == 0);
Also If you create all your students in quick succession there's a good chance that your current code will return the same value for subsequent calls.
Well.
Consider what is happening here. When your Student is constructued, you get some random number, and then set it to the member variable level.
Then, at some other point, you call a function, readingLevel, which returns this previously set value.
Then, you may ponder to yourself: Exactly when would this function give a different value? Well, it will only do so when level gets a different value. And when does that happen? Well, it only happens in the constructor, so, that means, it never happens again for the life of the object ....
Try the following. Move the selection of the random level to the readingLevel function.
Random random = new Random();
public Student()
{
}
public bool readingLevel()//this always returns one value for the entire program.
{
int randomLevel=random.Next(1,3);
level = (randomLevel % 2 == 0);
return level;
}
That is because you are using the random.Next() and the level evaluation within the constructor of your class, remember that the constructor is only executed when you create a new instance of your object, for having it executed several times create a different method where you call the random and the level evaluation, that way you'll get different values every time or use Something like this:
public bool Level()
{
int randomLevel=random.Next(1,3);
level = (randomLevel % 2 == 0);
return level;
}
Random random = new Random(DateTime.Now.Ticks);

Categories

Resources